如何在DbSet.Find()中包含相关表?
如果我想在EF7查询中包含相关对象,那么它很简单:
var myThing = db.MyThings .Include(t => t.RelatedThing) .Where(t => t.SomeCondition == true) .ToList();
此外,在DbSet
上有一个很好的方法,可以通过其键轻松加载单个对象:
var myThing = db.MyThings.Find(thingId);
但是现在我想通过它的Id加载myThing
,以及它的RelatedThing
。 不幸的是(并且可以理解) .Find()
是DbSet
的方法,而不是IQueryable
。 显然我可以做到这一点:
var myThing = db.MyThings .Include(t => t.RelatedThing) .SingleOrDefault(t => t.MyThingId == thingId);
但我特别想使用.Find()
方法,因为它很好且通用,而且我正在编写一个通常加载记录的方法以及由Expression<Func>
指定的“包含”关系。
有什么建议怎么做?
使用EF6是不可能的,我不认为EF Core会改变它。 这是因为Find
方法的主要目的是从本地缓存中引入已加载的实体,或者如果不存在则从数据库加载它。 因此,急切加载( Include
)只能在后一种情况下使用,而在前者中则需要执行显式加载。 在单一方法中将两者结合起来可能在技术上是可行的,但很难。
我认为您应该将FirstOrDefault
(或SingleOrDefault
)路由与急切加载相结合。 您可以使用预先加载在Repositorygenerics方法GetById中查看EF6的示例实现。 可以像使用dbContext.Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties
一样调整EF dbContext.Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties
用于查找PK属性和构建谓词的属性。 此外,由于EF Core包含更复杂(需要Include
/ ThenInclude
链),您可能会发现这个线程有趣可以在Entity Framework Core中创建基于String的Include替代方案吗? 。
将Find与Load结合使用,可显式加载相关实体。 在MSDN示例下面:
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(); }
这是MSDN链接