如何告诉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方法去掉额外的行吗?
答案 0 :(得分:10)
急切加载由Include
方法完成:
db.People.Include(p => p.Secondary)
例如,FirstOrDefault(p => p.Id == id)
可以跟着。
Find
是DbSet
方法,首先尝试在上下文缓存中查找请求的实体。只有在那里找不到它时,才从数据库中取出实体。
由于(Find
)的这种特殊行为,Include
和Find
无法混合。当在缓存中找到根实体时,很难定义要做什么,但要包含的实体不是(或仅部分)。它们应该从数据库中提取吗?这意味着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();