首页 > 解决方案 > AutoMapper > 使用可查询扩展和一些映射失败

问题描述

有没有办法EntityFramework用 AutoMapper 映射这些实体?

尝试将DateTime对象(从我的 DBContext 实体)映射到TimeSpan我的 DTO 上的属性时出现错误。

这是例外

----------- Exception #0 -----------
Type: System.NotSupportedException
Message: The specified type member 'TimeOfDay' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Source: EntityFramework

它曾经在调用后映射实体时工作ToList(),但现在使用 AutoMapper 的ProjectTo<>IQueryable 扩展,它显然试图将表达式转换为 SQL 可以理解的表达式。

我的问题 - 是否可以在服务器上执行查询后配置某些对象的映射?(例如ToList()通话后)

DB 实体上的 CloseTime 属性是一个DateTime对象,但我们正在映射到一个TimeSpan对象

现在 - 我只是忽略这样的属性

cfg.CreateMap<CustomerShipTo, ShipToBase>()
    .ForMember(desc => desc.OpenTime, src => src.Ignore())
    //.ForMember(desc => desc.OpenTime, src => src.CloseTime.TimeOfDay)
    .ReverseMap();

标签: c#entity-frameworkautomapperiqueryable

解决方案


.ProjectTo()需要能够最终映射到 SQL,因此与使用.Map(). 解决此类问题的方法是映射“原始”数据值,然后在 DTO 中使用转换属性。在您的情况下,由于这是一种数据类型转换,您可以调用原始值“OpenDateTime”,通常如果我想使用相同的名称,我将使用前缀“Raw”来反映原始 DB 值。(即 RawOpenTime)

[Serializable]
public class ShipToBase
{
    // ...
    public DateTime OpenDateTime { get; set; }
    public Timespan OpenTime
    {
        get { OpenDateTime.TimeOfDay; }
        set { OpenDateTime = DateTime.MinValue().Add(value); } // Setter if needed.
    }
}

然后在映射中:

cfg.CreateMap<CustomerShipTo, ShipToBase>()
    .ForMember(desc => desc.OpenDateTime, src => src.OpenTime)
    .ForMember(desc => desc.OpenTime, src => src.Ignore())
    .ReverseMap();

推荐阅读