【问题标题】:Automapper Project usingAutomapper 项目使用
【发布时间】:2017-10-30 15:13:13
【问题描述】:

我目前在后端使用自动映射器将对象映射到模型。 我最近决定使用以下代码来处理我所有的时区转换:

  cfg.CreateMap<DateTime?, DateTime?>()
  .ProjectUsing(i => DbFunctions.AddHours(i, offset.Hours));

  cfg.CreateMap<DateTime, DateTime>()
  .ProjectUsing(i => DbFunctions.AddHours(i, offset.Hours).Value);


  Object.ProjectTo<ObjectModel>().SingleOrDefault();

然后它工作正常,对象被映射并转换时区

但是,当我在业务层中使用以下代码进行单个对象映射时:

Mapper.Map<Object, ObjectModel>(singleRecord); 

它给出了一个错误: 此函数只能从 LINQ to Entities 调用。

堆栈跟踪:

at System.Data.Entity.DbFunctions.AddHours(Nullable`1 timeValue, Nullable`1 addValue)
   at lambda_method(Closure , DateTime , DateTime , ResolutionContext )
   at AutoMapper.ResolutionContext.Map[TSource,TDestination](TSource source, TDestination destination)
   at lambda_method(Closure , Inventory , InventoryModel , ResolutionContext )

Mapper.Map 在特定场景中使用很重要,我也不想投影单个记录。

有没有办法解决这个问题?

【问题讨论】:

    标签: c# .net entity-framework linq automapper


    【解决方案1】:

    默认情况下,AutoMapper 将通过编译传递给ProjectUsing 并由ProjectTo 使用的Expression&lt;TFunc&lt;TSource, TDestionation&gt;&gt; 来构建一个映射Func&lt;TSource, TDestination&gt;&gt; 以供Map 方法使用,因为通常它已经足够并且有效。但不适用于 EF 规范函数。

    您可以通过显式提供ProjectUsingConvertUsing 来指定与Map 方法一起使用的不同转换来覆盖该行为:

    var map1 = cfg.CreateMap<DateTime?, DateTime?>();
    map1.ProjectUsing(i => DbFunctions.AddHours(i, offset.Hours));
    map1.ConvertUsing(i => i?.AddHours(offset.Hours));
    
    var map2 = cfg.CreateMap<DateTime, DateTime>();
    map2.ProjectUsing(i => DbFunctions.AddHours(i, offset.Hours).Value);
    map2.ConvertUsing(i => i.AddHours(offset.Hours));
    

    【讨论】:

    • 嘿@ivan,感谢您的回答,我认为它正在工作,我正在实施它。
    • 您能向我解释一下吗:projectusing 是否在数据库级别上运行?转换使用在 Cpu 级别上运行吗? EF Canonical 函数的含义和作用是什么?
    • (1) EF 规范函数是来自DbFunctions 的函数。正如您所注意到的,它们并不是要被执行的。就像IQueryable 表达式树中已知的“占位符”一样,EF 查询翻译器将它们映射到 SQL 查询中相应的数据库函数调用。 (2) 是的,由于ConvertUsing 接收到Func&lt;...&gt;(读取-代码),它不能映射到SQL,所以它被Map 方法使用,这些方法在内存对象中进行操作。
    • 你是传奇伊万!您是否正在寻找一份全职工作?地点是迪拜
    • 呵呵,谢谢,很高兴它帮助了你。不,谢谢,但我喜欢我现在住的地方:)
    【解决方案2】:

    来自 MSDN:

    提供公开 EDM 规范 > 函数的公共语言运行时 (CLR) 方法,以便在 DbContext 或 ObjectContext LINQ to Entities 查询中使用。

    因此该错误是意料之中的,因为投影未在 LINQ to Entities 查询中执行。

    DbFuncions.AddHours() 调用被转换为数据库函数。由于在您的业务层中您不是传递实体而是传递对象,因此会引发错误。

    您有两种方法可以解决此问题: 1. 在业务层中使用不同的映射逻辑。 2. 使用不依赖DbFunctions 类的映射逻辑,以便在您的DAL 和业务层中使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多