Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper Project using

I am currently using automapper in my backend to map objects to models. I recently decided to use the following code to handle all my timezone conversions:

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

then it works fine and the object is mapped and timezone converted

However when i am using the following code in my business layer to do a single object mapping:

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

It Gives an error : This function can only be invoked from LINQ to Entities.

stack trace :

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 is important to use in specific scenarios and i also don't want to project single records.

is there a way round this ?

like image 963
DaGeek Avatar asked Oct 26 '25 05:10

DaGeek


2 Answers

By default AutoMapper will build a mapping Func<TSource, TDestination>> to be used by Map method by compiling the Expression<TFunc<TSource, TDestionation>> passed to ProjectUsing and used by ProjectTo, because usually it's enough and works. But not with EF canonical functions.

You could override that behavior by specifying a different conversion to be used with Map method by providing explicitly both ProjectUsing and ConvertUsing:

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));
like image 197
Ivan Stoev Avatar answered Oct 28 '25 18:10

Ivan Stoev


From MSDN:

Provides common language runtime (CLR) methods that expose EDM canonical >functions for use in DbContext or ObjectContext LINQ to Entities queries.

So the error is to be expected because the projection is not executed in a LINQ to Entities query.

The DbFuncions.AddHours() call is translated to a database function. Since in your business layer you're not passing an entity but an object, the error is thrown.

You have two ways to work around the problem: 1. Use a different mapping logic in your bussiness layer. 2. Use a mapping logic that does not depend on the DbFunctions class so that it can be used in your DAL and business layer.

like image 34
Hintham Avatar answered Oct 28 '25 18:10

Hintham



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!