如何在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链接