实体框架 - 渴望加载相关实体

时间:2010-09-08 19:21:39

标签: .net entity-framework entity-framework-4 eager-loading

我正在使用带有MVC的Entity Framework 4,并且需要确保在我的视图中使用的任何引用实体在控制器方法返回之前已经加载,否则视图会吐出可怕的:

  

ObjectContext实例已被释放,不能再用于需要连接的操作。

直接从上下文中选择时,我可以使用Include(string)方法强制它们包含在生成的SQL查询中:

var sellers = context.Sellers.Include("Recommendations.User").ToList();

但是,如果我(例如)一个接受实体并需要加载所有项目的辅助方法,则没有Include方法可用。

void Test(Seller seller)
{
    // ensure all recommendations and their users are loaded
}

蛮力方法是循环使用它们:

foreach (var recommendation in seller.Recommendations)
    recommendation.User.ToString(); // just force a load

如果我有100条建议,这将在幕后创建101个SQL查询。理想情况下,我想要一个方法/方法来加载所有RecommendationUser对象,只需要一次SQL访问。

告诉我钱。

编辑我真的不想讨论这是一个好的还是坏的架构。为了这个问题,我简化了我的方案。你能用EF API做我想问的事吗?

编辑2

Ladislav's edit为一种新方法提供了希望,但似乎我并不存在。

我可以通过这个来实现我的目标:

context.Sellers.Include("Recommendations.User").Single(s => s.Id == seller.Id);

此方法无法使用LoadProperty ...

context.LoadProperty(seller, "Recommendations.User");

...因错误而失败......

  

找不到指定的导航属性Recommendations.User。

如果您没有对上下文的引用,这些方法都不起作用。

4 个答案:

答案 0 :(得分:5)

这是一个老问题,但在EF6中,您可以在this等实体上完成加载相关对象:

context.Entry(seller).Collection(s => s.Recommendations).Query().Include(r => r.User)).Load();

这会加载给定Recommendations的所有Users及其相关seller

答案 1 :(得分:3)

我认为这是您的存储库的工作,在您的情况下应该公开GetFullSeller(Include加载的所有属性)和GetSeller(仅基础实体)等方法。

修改

如何在EF v4中加载导航属性有几种方法。

没有自动加载。

答案 2 :(得分:2)

我处于同样的境地。我认为使用EF很容易陷入101查询问题。

解决方案可以是创建Seller类的部分类(由EF生成)并实现返回IQueryable的GetSubclassNameQ,以及返回带有预先加载的IQueryable的GetSubclassNameQFull。

public partial class Seller{

  public IQueryable<Recommendation> GetRecommendationsQ(EntityContainer entitycontainer) {
    return entitycontainer.Recommendations;
  }      

  public IQueryable<Recommendation> GetRecommendationsQFull(EntityContainer entitycontainer) {
    return this.GetRecommendationsQ(entitycontainer).Include("Recommendations.User");
  }

  public IQueryable<Recommendation> GetRecommendationsQ() {
    return GetRecommendationsQ(new EntityContainer());
  }

  public IQueryable<Recommendation> GetRecommendationsQFull() {
    return this.GetRecommendationsQ().Include("Recommendations.User");
  }

}

答案 3 :(得分:0)

您可能希望使用控制器将它们映射到更好地表示视图实际显示内容的Model对象,而不是将实际的域对象(EntityObject s)传递给视图。这将减少View中所需的逻辑量,并且避免在上下文过期后避免传递EntityObjects的令人愉快的副作用。

根据您的修改

修改

不,API没有办法获取单个实体对象并使其所有类型的其他实体对象在一次性延迟填充特定属性的同时加载。您最好使用Include提及的方式将所有项目拉出来,就像您在问题中所示。