繁体   English   中英

地图ICollection <Model> 列出 <ViewModel> 使用AutoMapper

[英]Map ICollection<Model> to List<ViewModel> using AutoMapper

我正在尝试在代码中使用AutoMapper。 映射集合时,出现此错误

LINQ to Entities无法识别方法“ System.Collections.Generic.List 1[Web.ViewModels.FirmMatterViewModel] Map[ICollection 1,List 1](System.Collections.Generic.ICollection 1 [Web.Models.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)
    };

我已经为FirmMatter创建了地图

Mapper.CreateMap<FirmMatter, FirmMatterViewModel>();

我的代码有什么问题?

我知道您接受了答案,但是我要么不会使用AutoMapper来执行此操作,要么不会一直使用AutoMapper来执行。

Include s和AsEnumerable()的组合效率很低,因为SQL语句将选择所有表的所有列并将此膨胀的结果集拉入内存。 最后,您只需要数量非常有限的属性。 为什么不寻找一种只选择所需数据的方法呢?

没有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 { ... } }
    };

您不需要在此处包含,因为查询不会返回可在其中包含集合和引用的ClientMatter对象。 select使用这些导航属性足以使EF生成所有必需的联接。

使用AutoMapper

如果您还定义了ClientMatterClientMatterIndexListViewModel之间的映射,则可以使用AutoMapper的Project.To方法获得与上一个查询相同的效果:

using AutoMapper.QueryableExtensions;
...

var clientMatters = db.ClientMatters
                      .Project().To<ClientMatterIndexListViewModel>();

为此, ClientMatterIndexListViewModel应该包含如下属性:

public IEnumerable<FirmMatterViewModel> FirmMatters { get; set; }

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)
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM