使用 AutoMapper 将 ICollection<Model> 映射到 List<ViewModel>
Map ICollection<Model> to List<ViewModel> using AutoMapper
我正在尝试在我的代码中使用 AutoMapper。映射集合时,出现此错误
LINQ to Entities does not recognize the method
'System.Collections.Generic.List1[Web.ViewModels.FirmMatterViewModel]
Map[ICollection
1,List1](System.Collections.Generic.ICollection
1[Web.Models.FirmMatter])'
method, and this method cannot be translated into a store expression.
这是我如何进行映射的代码:
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)
};
我已经为 FirmMatter 创建了地图
Mapper.CreateMap<FirmMatter, FirmMatterViewModel>();
我的代码有什么问题?
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)
});
我知道你接受了一个答案,但我要么不使用 AutoMapper,要么一直使用 AutoMapper。
Include
s 和 AsEnumerable()
的组合效率很低,因为 SQL 语句将 SELECT 所有表的所有列并将这个臃肿的结果集拉入内存.最后你只需要非常有限的属性。为什么不寻找一种只 select 所需数据的方法?
没有 AutoMapper
不使用 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 { ... } }
};
此处不需要包含,因为查询不会 return ClientMatter
可以包含集合和引用的对象。在 select
中使用这些导航属性足以让 EF 生成所有必需的连接。
使用 AutoMapper
如果您还定义了 ClientMatter
和 ClientMatterIndexListViewModel
之间的映射,您可以使用 AutoMapper 的 Project.To
方法来获得与前面查询相同的效果:
using AutoMapper.QueryableExtensions;
...
var clientMatters = db.ClientMatters
.Project().To<ClientMatterIndexListViewModel>();
要做到这一点,ClientMatterIndexListViewModel
应该包含这样的 属性:
public IEnumerable<FirmMatterViewModel> FirmMatters { get; set; }
我正在尝试在我的代码中使用 AutoMapper。映射集合时,出现此错误
LINQ to Entities does not recognize the method 'System.Collections.Generic.List
1[Web.ViewModels.FirmMatterViewModel] Map[ICollection
1,List1](System.Collections.Generic.ICollection
1[Web.Models.FirmMatter])' method, and this method cannot be translated into a store expression.
这是我如何进行映射的代码:
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)
};
我已经为 FirmMatter 创建了地图
Mapper.CreateMap<FirmMatter, FirmMatterViewModel>();
我的代码有什么问题?
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)
});
我知道你接受了一个答案,但我要么不使用 AutoMapper,要么一直使用 AutoMapper。
Include
s 和 AsEnumerable()
的组合效率很低,因为 SQL 语句将 SELECT 所有表的所有列并将这个臃肿的结果集拉入内存.最后你只需要非常有限的属性。为什么不寻找一种只 select 所需数据的方法?
没有 AutoMapper
不使用 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 { ... } }
};
此处不需要包含,因为查询不会 return ClientMatter
可以包含集合和引用的对象。在 select
中使用这些导航属性足以让 EF 生成所有必需的连接。
使用 AutoMapper
如果您还定义了 ClientMatter
和 ClientMatterIndexListViewModel
之间的映射,您可以使用 AutoMapper 的 Project.To
方法来获得与前面查询相同的效果:
using AutoMapper.QueryableExtensions;
...
var clientMatters = db.ClientMatters
.Project().To<ClientMatterIndexListViewModel>();
要做到这一点,ClientMatterIndexListViewModel
应该包含这样的 属性:
public IEnumerable<FirmMatterViewModel> FirmMatters { get; set; }