IQueryable Lambda投影语法

Har*_*per 6 lambda linq-to-objects linq-to-entities iqueryable projection

我有一个IQueryable,其实体框架4对象我想投影到他们的DTO等价物.一个这样的对象'Person'是EF4类,相应的POCO PersonP是我定义的类.我正在使用Automapper在它们之间进行映射.但是,当我尝试以下代码时:

IQueryable<Person> originalModel = _repo.QueryAll();
IQueryable<PersonP> projection = originalModel.Select(e => Mapper.Map<Person, PersonP>(e));
Run Code Online (Sandbox Code Playgroud)

投影在运行时生成此错误:

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.
Run Code Online (Sandbox Code Playgroud)

IQueryable<PersonP>使用Automapper 创建投影的合适语法是什么?谢谢.

PS Automapper配置正确 - 我在其他地方使用它在Person和PersonP之间来回转换,即Mapper.Map<Person, PersonP>(myPersonObject)正确返回一个PersonP对象.

编辑(更多代码):

我正在使用它来帮助函数将EF4实体POCO(PersonP)绑定到Telerik网格 - 由于它们包含循环引用(即导航属性),因此不会正确地序列化实体本身.我的代码看起来像这样:

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...
}
Run Code Online (Sandbox Code Playgroud)

.ToGridModel方法是一个扩展方法IQueryable,它返回一个我无法可靠解析的复杂对象 - 这使我相信在完成对POCO的投影后我必须执行过滤.

更新2:

为了简化事情,我做了一个非泛型方法,如下所示:

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 };
}
Run Code Online (Sandbox Code Playgroud)

创建投影时,此代码也会失败.我注意到IQueryable.Select()有多个重载:Expression>是其中之一.我可以使用其中一个重载来表示此函数/委托调用吗?

Nat*_*han 11

AutoMapper的作者现在已经解决了这个问题:http://lostechies.com/jimmybogard/2011/02/09/autoprojecting-linq-queries/

他提供了一个实现,它采用所需的投影和查询,并仅查询数据库中投影映射所需的字段.

另外,请参阅Paul Hiles 的后续文章,了解一些缓存方面的改进.

希望这可以帮助.


Cra*_*ntz 5

使用Automapper创建IQueryable投影的合适语法是什么?

没有一个.Automapper不会这样做.这是这项工作的错误工具.

可以创建一个类似Automapper的工具来为查询投影做类似的事情.我过去曾考虑过它,但总是得出结论,使用它的代码比投影的可读性差.我不想在代码读取时间内优化代码写入时间.

您更新的代码不起作用,因为它不是表达式.如果你这样做:

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

...然后:

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

......那就行了.

  • 这个答案不再正确(虽然它在给出时是正确的).此功能现在可在AutoMapper中使用:https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions (2认同)