Reputation: 43
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 ?
Upvotes: 4
Views: 3996
Reputation: 205569
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));
Upvotes: 2
Reputation: 1086
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.
Upvotes: 1