EF5 ObjectContext:如何用context.T.Attach()</t>替换IQueryable <t> .Include(Path)

时间:2012-11-14 16:30:39

标签: c# entity-framework reflection

我在一个相对庞大而复杂的数据模型上使用Entity Framework 5和ObjectContext。 我想解决将多个IQueryable.Include(Path)链接到急切加载相关对象时生成的大查询。

例如,我做这样的事情:

var queryPe = context.Person.Where(p => p.Id == 110).Include(@"AA");
queryPe = queryPe.Include(@"BB.CC.DD");
queryPe = queryPe.Include(@"EE.FF");

通过使用字符串数组并在foreach循环中在运行时链接每个图形,可以使它成为通用的。

相反,我想做这样的事情:

Person pe = context.Person.Where(p => p.Id == 110).First();
context.LoadProperty(pe, "AA");
pe.BB.Attach(pe.BB.CreateSourceQuery().Include(@"CC.DD"));
pe.EE.Attach(pe.EE.CreateSourceQuery().Include(@"FF"));

我们将有4个较小的查询命中数据库而不是一个大查询。 当然,我仍然希望利用图形路径的功能作为字符串。

我可能错了,但这意味着我应该使用relexion按名称获取导航属性并在其上执行CreateSourceQuery(),因为没有这样的扩展方法来执行此操作。

我说错了吗?

编辑1 :嗯,我有一个额外的约束,就是我使用自我追踪实体(STE)。这意味着相关对象未实现为EntityCollection或EntityReference。所以Attach()和CreateSourceQuery()不可用!

因此,我坚持使用Context.LoadProperty来处理对象图。 这是唯一可能的吗?

编辑2 :由于DbContext类的帮助,解决了 EDIT 1 中出现的问题。请参阅以下代码:

Person pe = context.Person.Where(p => p.Id == 110).First();
context.LoadProperty(pe, "AA");
DbContext dbc = new DbContext(context, false);
dbc.Entry(pe).Collection(@"BB").Query().Include(@"CC.DD").Load();
dbc.Entry(pe).Reference(@"EE").Query().Include(@"FF").Load();

编辑3 02/11/2013 :上述代码存在问题(编辑2)。如果路径中的最后一个实体是引用而不是集合,则代码不会失败,但不会加载: - (

编辑4 :现在,我不是使用反射,而是通过在T4模板的帮助下查看实体数据模型来生成代码。

3 个答案:

答案 0 :(得分:1)

有时存储过程最好。编写一个返回多个结果集的存储过程,每个结果集对应一个您希望急切加载的实体类型。与您尝试完成的操作相比,这是高度高性能,并且存储过程将比每个引用/集合的包含和单独的加载语句更具可读性。是的,EF将自动挂钩相关实体!

以下是针对EDMX和代码的多个结果集的sprocs的参考:

http://msdn.microsoft.com/en-us/data/jj691402.aspx

答案 1 :(得分:0)

尝试在多个上下文中分隔聚合。每个有界上下文都应该有一个单独的上下文。这样您就可以创建一个松散耦合的实体框架解决方案。

朱莉·勒曼(Julie Lerman)有一个很好的关于这个概念的视频。

答案 2 :(得分:0)

我更喜欢使用存储过程。易于维护,工作更快等。