Using the Automapper project
I am currently using automapper in my server to map objects to models. I recently decided to use the following code to handle all of my timezones:
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 converted to timezone
However, when I use the following code in my business layer to create one object:
Mapper.Map<Object, ObjectModel>(singleRecord);
This gives an error: This function can only be called 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 essential for use in specific scenarios and I also don't want to design individual entries.
Is there a way to get around this?
source to share
By default, AutoMapper will build a mapping Func<TSource, TDestination>>
to be used by the method Map
compile Expression<TFunc<TSource, TDestionation>>
, passed to ProjectUsing
and used ProjectTo
, because that is usually enough and works. But not with the canonical EF features.
You can override this behavior by specifying another transformation that will be used with the method Map
, clearly indicating how 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));
source to share
From MSDN:
Provides common runtime (CLR) methods that expose canonical EDM functionality for use in DbContext or ObjectContext LINQ to Entities queries.
Therefore, you should expect an error because the projection is not done in the LINQ to Entities query.
The call is DbFuncions.AddHours()
transferred to a database function. Since in your business layer you are not passing an object, but an object, an error occurs.
You have two ways to solve the problem: 1. Use a different display logic in your business layer. 2. Use mapping logic that is class independent DbFunctions
, so it can be used in your DAL and business tier.
source to share