IQueryable Lambda Projection Syntax

前提是你 提交于 2019-12-21 04:59:11

问题


I have an IQueryable whose Entity Framework 4 objects I would like to project to their DTO equivalents. One such object 'Person' is an EF4 class, and the corresponding POCO PersonP is a class I've defined. I am using Automapper to map between them. However, when I try the following code:

IQueryable<Person> originalModel = _repo.QueryAll();
IQueryable<PersonP> projection = originalModel.Select(e => Mapper.Map<Person, PersonP>(e));

The projection generates this error at runtime:

LINQ to Entities does not recognize the method 'TestSite.Models.PersonP Map[Person,PersonP](TestSite.DataLayer.Model.Person)' method, and this method cannot be translated into a store expression.

What is the appropriate syntax to create a IQueryable<PersonP> projection using Automapper? Thank you.

P.S. Automapper is configured correctly - I use it in other places to convert back and forth between Person and PersonP, i.e. Mapper.Map<Person, PersonP>(myPersonObject) correctly returns a PersonP object.

EDIT (more code):

I'm using this for a helper function to bind EF4 Entity POCOs (PersonP) to a Telerik Grid - which will not serialize the entities themselves properly since they contain circular references (i.e. navigation properties). My code looks like this:

public static GridModel GetGridModel<TEntity, TPoco>(IRepository<TEntity> repo, GridState gridState) where TEntity : EntityObject
{
 var originalModel = repo.QueryAll().ToGridModel(gridState);
 var projection = originalModel.Select(e => Mapper.Map<TEntity, TPoco>(e));


 return projection.ToGridModel(gridState); // applies filters, sorts, pages, etc...
}

the .ToGridModel method is an extension method on IQueryable and it returns a complex object which I cannot reliably parse - so this leads me to believe I have to perform the filtering after I've done the projection to POCOs.

UPDATE 2:

Trying to simplify things, I made a non-generic method like this:

public static GridModel GetGridModel2(IRepository<Client> repo, GridState gridState)
{
 IQueryable<Client> originalModel = repo.QueryAll();
 IQueryable<ClientP> projection = originalModel.Select(c => ClientToClientP(c));

 return projection.ToGridModel(gridState);
}

private static ClientP ClientToClientP(Client c)
{
 return new ClientP { Id = c.Id, FirstName = c.FirstName };
}

This code also fails when creating the projection. I notice that IQueryable.Select() has multiple overloads: Expression> being one of them. Could I represent this function/delegate call using one of these overloads?


回答1:


What is the appropriate syntax to create a IQueryable projection using Automapper?

There isn't one. Automapper doesn't do this. It's the wrong tool for this job.

One could create an Automapper-like tool to do a similar thing for query projections. I've considered it in the past, but always concluded that code using it would be less readable than the projection. I don't want to optimize code-writing time over code-reading time.

Your updated code doesn't work because it isn't an expression. If you do:

private static Expression<Func<Client, ClientP>> ClientP ClientToClientP()
{
    return c => new ClientP { Id = c.Id, FirstName = c.FirstName };
}

...and then:

IQueryable<Client> originalModel = repo.QueryAll();
Expression<Func<Client, ClientP>> exp = ClientToClientP();
IQueryable<ClientP> projection = originalModel.Select(exp);

...then it will work.




回答2:


This has actually been solved now by the author of AutoMapper here: http://lostechies.com/jimmybogard/2011/02/09/autoprojecting-linq-queries/

He provides an implementation that takes a desired projection and the query and queries the database for only the fields needed for the projection mapping.

Also, see the follow-on article by Paul Hiles for some caching improvements.

Hope this helps.




回答3:


If you add .ToList() before the Select you can force the mapping to happen client-side (Linq to Objects) instead of server side (SQL). Just make sure you've done your filtering first so you aren't bringing the whole table over.



来源:https://stackoverflow.com/questions/4040551/iqueryable-lambda-projection-syntax

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