如何使用DBContext Find方法指定预先加载

时间:2016-08-22 21:16:11

标签: c# asp.net-mvc entity-framework

如何告诉DBContext的Find方法应该急切加载导航属性/实体?

我有以下代码删除与相关辅助实体的关联:

Person primary = db.People.Find(Id);
if (primary == null)
  return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

// This line is required to load the related entity
db.Entry(primary).Reference("Secondary").Load();

primary.Secondary = null;
db.SaveChanges();

我必须添加行db.Entry(primary).Reference("Secondary").Load();才能使其正常工作。我理解这是因为实体框架正在使用延迟加载。我可以在Find方法中覆盖它,并通过使用Eager版本的Find方法去掉额外的行吗?

5 个答案:

答案 0 :(得分:10)

急切加载由Include方法完成:

db.People.Include(p => p.Secondary)

例如,FirstOrDefault(p => p.Id == id)可以跟着。

FindDbSet方法,首先尝试在上下文缓存中查找请求的实体。只有在那里找不到它时,才从数据库中取出实体。

由于(Find)的这种特殊行为,IncludeFind无法混合。当在缓存中找到根实体时,很难定义要做什么,但要包含的实体不是(或仅部分)。它们应该从数据库中提取吗?这意味着Find + Include 总是必须在数据库中查询所包含的实体,因为它不能依赖本地缓存来完成。那会破坏Find的目的。或者,如果根实体位于本地缓存中,则应该只找到本地缓存中的实体?这会使方法的结果不明确。

在ASP.Net MVC(或Web API)操作方法中,Find几乎没有用处,因为大多数时候,将创建一个新的上下文,并从数据库中提取一次实体。换句话说,缓存中没有任何内容可以返回。您可能希望使用该方法的简洁性,但有关数据库往返的效果与FirstOrDefault()相同。

答案 1 :(得分:1)

或者您可以使用

var result = db.Person.Include(c=>c.Secondary).FirstOrDefault(entity=>entity.Id == Id);

在Include中使用using System.Data.Entity;作为Linq功能,否则你可以使用字符串" Secondary"像这样:.Include("Secondary")

答案 2 :(得分:1)

只需使用Include方法:

  

var result = db.Person.Include(c => c.Secondary).FirstOrDefault(entity => entity.Id == Id);

参考:

http://www.entityframeworktutorial.net/EntityFramework4.3/eager-loading-with-dbcontext.aspx

答案 3 :(得分:0)

要回答有关如何在显式加载(from here)中使用Find方法的原始问题?

using (var context = new BloggingContext())
{
    var post = context.Posts.Find(2);

    // Load the blog related to a given post.
    context.Entry(post).Reference(p => p.Blog).Load();

    // Load the blog related to a given post using a string.
    context.Entry(post).Reference("Blog").Load();

    var blog = context.Blogs.Find(1);

    // Load the posts related to a given blog.
    context.Entry(blog).Collection(p => p.Posts).Load();

    // Load the posts related to a given blog
    // using a string to specify the relationship.
    context.Entry(blog).Collection("Posts").Load();
}

要添加到@GertArnolds帖子中,如果您使用依赖项注入,并且在每个Scoped生活方式中加载一次DbContext,则本质上是:(from here):

容器将为每个Web请求创建一个实例。 在ASP.NET Web窗体和ASP.NET MVC应用程序中使用这种生活方式。

然后DbContext停留了一段时间。

答案 4 :(得分:-4)

只需更改

Person primary = db.People.Find(Id);

Person primary = db.People.Find(Id).FirstOrDefault();
相关问题