问题描述
我有一个IQueryable,我想将其Entity Framework 4对象投影到其DTO等效项.这样的对象"Person"是EF4类,而对应的POCO PersonP是我定义的类.我正在使用Automapper在它们之间进行映射.但是,当我尝试以下代码时:
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.
使用Automapper创建IQueryable<PersonP>
投影的合适语法是什么?谢谢.
What is the appropriate syntax to create a IQueryable<PersonP>
projection using Automapper? Thank you.
P.S. Automapper的配置正确-我在其他地方用它来在Person和PersonP之间来回转换,即Mapper.Map<Person, PersonP>(myPersonObject)
正确返回了PersonP
对象.
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.
编辑(更多代码):
我将此用于辅助功能以将EF4实体POCO(PersonP)绑定到Telerik网格-由于实体包含循环引用(即导航属性),因此无法正确地序列化实体本身.我的代码如下:
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...
}
.ToGridModel
方法是IQueryable
的扩展方法,它返回一个我无法可靠地解析的复杂对象-因此这使我相信,在完成对POCO的投影后,我必须执行过滤.
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.
更新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 };
}
创建投影时,此代码也会失败.我注意到IQueryable.Select()有多个重载:Expression>是其中之一.我可以使用其中一种重载来表示此函数/委托调用吗?
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?
推荐答案
没有一个. Automapper不这样做.这是这项工作的错误工具.
There isn't one. Automapper doesn't do this. It's the wrong tool for this job.
可以创建类似于Automapper的工具来对查询投影执行类似的操作.我过去曾考虑过它,但总会得出结论,使用它的代码比投影的可读性差.我不想在代码读取时间上优化代码写入时间.
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 };
}
...然后:
IQueryable<Client> originalModel = repo.QueryAll();
Expression<Func<Client, ClientP>> exp = ClientToClientP();
IQueryable<ClientP> projection = originalModel.Select(exp);
...那么它将起作用.
...then it will work.
这篇关于可查询的Lambda投影语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!