我有一个 IQueryable,我想将其 Entity Framework 4 对象投影到他们的 DTO 等价物。一个这样的对象“Person”是一个 EF4 类,相应的 POCO PersonP 是我定义的一个类。我正在使用 Automapper 在它们之间进行映射。但是,当我尝试以下代码时:
IQueryable<Person> originalModel = _repo.QueryAll();
IQueryable<PersonP> projection = originalModel.Select(e => Mapper.Map<Person, PersonP>(e));
投影在运行时生成此错误:
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.
创建
IQueryable<PersonP>
的适当语法是什么?使用 Automapper 进行投影?谢谢你。附言Automapper 配置正确 - 我在其他地方使用它在 Person 和 PersonP 之间来回转换,即
Mapper.Map<Person, PersonP>(myPersonObject)
正确返回 PersonP
目的。编辑(更多代码):
我使用它作为辅助函数将 EF4 实体 POCO (PersonP) 绑定(bind)到 Telerik Grid - 由于它们包含循环引用(即导航属性),因此它们不会正确序列化实体本身。我的代码如下所示:
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...
}
.ToGridModel
method 是 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 };
}
创建投影时,此代码也会失败。我注意到 IQueryable.Select() 有多个重载: Expression> 是其中之一。我可以使用这些重载之一来表示这个函数/委托(delegate)调用吗?
最佳答案
AutoMapper 的作者现在实际上已经解决了这个问题:http://lostechies.com/jimmybogard/2011/02/09/autoprojecting-linq-queries/
他提供了一个实现,该实现采用所需的投影和查询,并仅查询数据库中投影映射所需的字段。
另见 follow-on article Paul Hiles 进行了一些缓存改进。
希望这可以帮助。
关于linq-to-entities - IQueryable Lambda 投影语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4040551/