Automapper mapping function

佐手、 提交于 2019-12-11 06:06:39

问题


Hello everyone I am trying to achieve something relatively simple in Automapper but I keep on failing. I am trying to map a property on my Dto with a function expression

   .ForMember(dest => dest.HasPaid, opt => opt.MapFrom(c => MapHasPaid(c)))

    private bool MapHasPaid(AppUser src)
    {
        var lastPayment = src.RentPayments.OrderByDescending(p => p.DateTo).FirstOrDefault();
        if (lastPayment == null)
        {
            return false;
        }

        return lastPayment.DateFrom.Date <= DateTime.Now.Date &&
               DateTime.Now.Date <= lastPayment.DateTo.Date;
    }

This returns

LINQ to Entities does not recognize the method 'Boolean MapHasPaid(xxxx.Models.AppUser)' method, and this method cannot be translated into a store expression.

I tried with a IValueResolver

public class CustomResolver : IValueResolver<AppUser, HouseMateEntity, bool>
{
    public bool Resolve(AppUser source, HouseMateEntity destination, bool member, ResolutionContext context)
    {
        var lastPayment = source.RentPayments.OrderByDescending(p => p.DateTo).FirstOrDefault();
        if (lastPayment == null)
        {
            return false;
        }

        return lastPayment.DateFrom.Date <= DateTime.Now.Date &&
               DateTime.Now.Date <= lastPayment.DateTo.Date;
    }
}


.ForMember(dest => dest.HasPaid, opt => opt.ResolveUsing<CustomResolver>())

but give me the following exception

Can't resolve this to Queryable Expression

How can I map my property as a result of more complex query?

thanks

I have also tried the simple case on the documentation https://github.com/AutoMapper/AutoMapper/wiki/Custom-value-resolvers

same error exception

Can't resolve this to Queryable Expression

Has anyone got ResolveUsing to work? is this an automapper bug?

EDIT: the only way I could get this working is with the following, and it really smells bad to me

.ForMember(dest => dest.HasPaid,
                   opt => opt.MapFrom(c => DbFunctions.TruncateTime(c.RentPayments.OrderByDescending(p => p.DateTo).FirstOrDefault().DateFrom) <= DbFunctions.TruncateTime(DateTime.Now) &&
                                      DbFunctions.TruncateTime(DateTime.Now) <= DbFunctions.TruncateTime(c.RentPayments.OrderByDescending(p => p.DateTo).FirstOrDefault().DateTo)));

回答1:


I expect you are attempting to use this with AutoMapper's Projection? The issue is that the Resolve functions you are attempting to implement are making calls that are not translatable in LINQ to Entities. Basically LINQ does not have a mapping between one of the C# calls you're making to some corresponding SQL to run on the database.

The reason your last bit of code works is because you are using the DbFunctions class which implements all the necessary logic to handle datetime manipulation in LINQ to Entities or LINQ to SQL.

Either use the DbFunctions methods exactly like you are or first retrieve the data (call .ToList() or similar on the query) and then map to your Target type.

This is documented in the AutoMapper documentation.

EDIT:

If you are using the AutoMapper Queryable Extensions then ResolveUsing is NOT supported AutoMapper documentation: Supported mapping options



来源:https://stackoverflow.com/questions/44087825/automapper-mapping-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!