1

I'm using Entity Framework 6.2.0 and Automapper 6.2.2. I need to map the entity Cart to CartDto. CartDto has a property Total which needs to be mapped to the result of Cart.GetTotal(). I'd like to use .ProjectTo to simplify the query, but if I do that I receive the error:

LINQ to Entities does not recognize the method GetTotal()

because the projection uses IQueryable and the method has no translation in SQL. Is there any way around this issue?

var automapperConfiguration = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Cart, CartDto>()
       .ForMember(x => x.Total, o => o.MapFrom(x => x.GetTotal()))
       .ForAllOtherMembers(x => x.Ignore());
});

var cartDto = dbContext.Carts
                       .ProjectTo<CartDto>(automapperConiguration)
                       .FirstOrDefault();
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
tocqueville
  • 5,270
  • 2
  • 40
  • 54
  • What does the GetTotal() method do? Could you replace x => x.GetTotal() with x => x.Sum(row => row.Quantity) or x => x.Count() for example. – Morph Aug 24 '18 at 15:04
  • No unfortunately, the method is quite complex and I want to keep the logic in one place. I also have many other methods like this one, this is only an example. – tocqueville Aug 24 '18 at 15:33

1 Answers1

2

This is not AutoMapper not allowing this, it's Entity Framework. AutoMapper merely takes your mapping configuration and builds a Select LINQ expression to the underlying query provider.

In your case, the underlying query provider is Entity Framework, which unsurprisingly won't understand any random method and how to translate that method into SQL. EF understands a few methods, like Count, Sum, some string/DateTime/primitive methods, but that's about it.

So the exception message is quite accurate - EF doesn't understand this method you've given it, and therefore has no way to translate that method to SQL.

There may be hope, however, if you check out the AutoMapper.EF6 package. It includes the DelegateDecompiler package that uses IL inspection to look at what your method does, de-compile it, and pass that result as an expression to the query provider.

If that seems complicated, it is, so you really better have an understanding of how LINQ works before proceeding.

Jimmy Bogard
  • 26,045
  • 5
  • 74
  • 69
  • As someone pretty new to .NET it bothers me that this is the only answer. It seems like what OP wants to do is pretty reasonable: retrieve some data from the database, have the server perform some logical manipulations of the data, then pass the data to the client. Of course it's nice when the form of the data to be passed to the client can be used to automatically optimise the SQL query but in this case, it isn't possible or appropriate. Is there really no way to tell LINQ that these data manipulations should NOT be optimised into SQL but instead just performed after the data is retrieved? – user2428107 Jan 26 '22 at 13:36
  • No, there is not. EF Core had a "feature" that when it encountered LINQ it couldn't understand, it would retrieve ALL data to the client. I've seen cases where it would return literally the entire table. It can't peek into your methods and properties to see exactly what is going on to know exactly what data to return. – Jimmy Bogard Jan 26 '22 at 14:16