我试图在我的代码中使用AutoMapper。映射集合时,我收到了此错误
LINQ to Entities无法识别该方法 ' {System.Collections.Generic.List {1}} 1,列表
1[Web.ViewModels.FirmMatterViewModel] Map[ICollection
1 [Web.Models.FirmMatter])' 方法,并且此方法无法转换为商店表达式。
这是我如何进行映射的代码:
1](System.Collections.Generic.ICollection
我为FirmMatter
创建了地图var clientMatters =
from cm in db.ClientMatters
.Include(t => t.Billing)
.Include(t => t.Billing.Office)
.Include(t => t.Billing.Client)
.Include(t => t.FirmMatters)
select new ClientMatterIndexListViewModel
{
ClientMatterID = cm.ClientMatterID,
BillingID = cm.BillingID,
OfficeName = cm.Billing.Office.Name,
ClientName = cm.Billing.Client.Name,
ClientMatterNo = cm.ClientMatterNo,
Description = cm.Description,
FirmMatters = Mapper.Map<ICollection<FirmMatter>, List<FirmMatterViewModel>>(cm.FirmMatters)
};
我的代码出了什么问题?
答案 0 :(得分:3)
我知道你接受了答案,但我要么不使用AutoMapper,要么一直使用AutoMapper。
Include
和AsEnumerable()
的组合非常低效,因为SQL语句将SELECT所有表的所有列并将此膨胀的结果集拉入内存。最后,您只需要非常有限的属性。为什么不寻找一种只选择所需数据的方法呢?
没有AsEnumerable()
和AM以及内联投影的查询效率更高:
var clientMatters =
from cm in db.ClientMatters
select new ClientMatterIndexListViewModel
{
ClientMatterID = cm.ClientMatterID,
BillingID = cm.BillingID,
OfficeName = cm.Billing.Office.Name,
ClientName = cm.Billing.Client.Name,
ClientMatterNo = cm.ClientMatterNo,
Description = cm.Description,
FirmMatters = cm.FirmMatters.Select(fm => new FirmMatterViewModel { ... } }
};
您不需要此处的“包含”,因为查询不会返回可包含集合和引用的ClientMatter
个对象。在select
中使用这些导航属性足以让EF生成所有必需的连接。
如果您还定义了ClientMatter
和ClientMatterIndexListViewModel
之间的映射,则可以使用AutoMapper的Project.To
方法获得与上一个查询相同的效果:
using AutoMapper.QueryableExtensions;
...
var clientMatters = db.ClientMatters
.Project().To<ClientMatterIndexListViewModel>();
为了实现这一点,ClientMatterIndexListViewModel
应包含如下属性:
public IEnumerable<FirmMatterViewModel> FirmMatters { get; set; }
答案 1 :(得分:2)
LINQ to Entities尝试将Map
方法转换为SQL,这显然是可撤消的。要避免该错误,您应该在调用map之前将查询转换为可枚举:
var query =
from cm in db.ClientMatters
.Include(t => t.Billing)
.Include(t => t.Billing.Office)
.Include(t => t.Billing.Client)
.Include(t => t.FirmMatters)
select cm;
var clientMatters = query.AsEnumerable().Select(cm => new ClientMatterIndexListViewModel
{
ClientMatterID = cm.ClientMatterID,
BillingID = cm.BillingID,
OfficeName = cm.Billing.Office.Name,
ClientName = cm.Billing.Client.Name,
ClientMatterNo = cm.ClientMatterNo,
Description = cm.Description,
FirmMatters = Mapper.Map<ICollection<FirmMatter>, List<FirmMatterViewModel>>(cm.FirmMatters)
});