IQueryable 实体框架 POCO 映射
Posted
技术标签:
【中文标题】IQueryable 实体框架 POCO 映射【英文标题】:IQueryable Entity Framework POCO Mappings 【发布时间】:2011-05-06 11:05:17 【问题描述】:我正在使用带有 EF4 的 ASP.NET MVC2。我需要为我的两个类 PersonP 和 AddressP 创建 POCO,它们对应于它们的 EF4“复杂”类(包括导航属性和 OnPropertyChanged() 等内容)。仅映射 PersonP 本身可以正常工作,但 PersonP 包含 AddressP(外键) - 如何使用 IQueryable 表达式映射它?
这是我尝试过的:
class AddressP
int Id get; set;
string Street get; set;
class PersonP
int Id get; set;
string FirstName get; set;
AddressP Address get; set;
IQueryable<PersonP> persons = _repo.QueryAll()
.Include("Address")
.Select(p => new PersonP
Id = p.Id,
FirstName = p.FirstName,
//Address = p.Address <-- I'd like to do this, but p.Address is Address, not AddressP
//Address = (p.Address == null) ? null :
//new AddressP <-- does not work; can't use CLR object in LINQ runtime expression
//
// Id = p.Address.Id,
// Street = p.Address.Street
//
);
如果没有.Include("Address")
,我将无法从地址表中检索任何内容,这是否正确?
如何使用上面的Select()
语句将Address
映射到PersonP
内的AddressP
?
谢谢。
【问题讨论】:
【参考方案1】:-
这是正确的,如果您禁用了延迟加载,或者您的对象上下文已经被释放并且不能用于使延迟加载工作。
是的,它不起作用,因为首先您需要执行查询然后开始映射它,否则您的映射逻辑将被视为在数据库中运行,因此会出现异常。 这样的事情会起作用:
// First we execute the query:
IQueryable<PersonP> persons = _repo.QueryAll().Include("Address").ToList();
// Now we have a IEnumerable and we can safely do the mappings:
persons.Select(p => new PersonP
Id = p.Id,
FirstName = p.FirstName,
Address = (p.Address == null) ? null : new AddressP()
Id = p.Address.Id,
Street = p.Address.Street
).ToList();
虽然此解决方案可以解决问题,但如果打算使用 POCO 类,您绝对应该考虑利用 EF4.0 POCO 支持并直接将 POCO 类与 EF 一起使用,而不是事后映射它们。一个很好的起点是这个演练: Walkthrough: POCO Template for the Entity Framework
【讨论】:
感谢您的回复,这正是我想要的。不幸的是,我必须将其保留为 IQueryable,因为我必须使用第三方方法应用过滤器/排序/分组,并且人员/地址存储库可能很大 - 所以我必须在执行实际查询之前执行此操作。我将研究 POCO EF4 支持 - 根据您的经验,您会推荐 NHibernate 解决方案吗? 我没有任何使用 NHibernate 的经验,但我认为不会有任何不同。您也可以查看 AsQueryable 以查看是否可以使用它,但我仍然认为 POCO 是在这种情况下要走的路。以上是关于IQueryable 实体框架 POCO 映射的主要内容,如果未能解决你的问题,请参考以下文章