【问题标题】:How to include related tables in DbSet.Find()?如何在 DbSet.Find() 中包含相关表?
【发布时间】:2017-10-05 22:10:56
【问题描述】:

如果我想在 EF7 查询中包含相关对象,这很简单:

var myThing = db.MyThings
                .Include(t => t.RelatedThing)
                .Where(t => t.SomeCondition == true)
                .ToList();

另外,DbSet<T> 上还有一个不错的方法,可以很容易地通过键加载单个对象:

var myThing = db.MyThings.Find(thingId);

但现在我想通过其 ID 加载 myThing,以及它的 RelatedThing。不幸的是(并且可以理解).Find()DbSet<T> 的一种方法,而不是IQueryable<T>。显然我可以这样做:

var myThing = db.MyThings
                .Include(t => t.RelatedThing)
                .SingleOrDefault(t => t.MyThingId == thingId);

但我特别想使用.Find() 方法,因为它既好用又通用,而且我正在编写一个方法,该方法通常加载记录以及Expression<Func<T, object>> 指定的“包含”关系。

有什么建议吗?

【问题讨论】:

  • 请原谅我的愚蠢问题,但我在 EF Core 中找不到 Find 方法,它位于何处?
  • @IvanStoev 它是DbSet<T> 类的一个方法,在Microsoft.EntityFrameworkCore 命名空间中。确保您使用的是最新的预发布版本。
  • 无论如何,我怀疑它是否可以用于预加载——在 EF6 中是不可能的。我想您将不得不使用类似 this 的东西,针对 EF Core 进行了调整。
  • @IvanStoev,这是个好建议。请你把它写下来作为答案吗?
  • @IvanStoev,很高兴在一个有答案的相关问题上找到你。

标签: c# entity-framework-core


【解决方案1】:

将 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 link

【讨论】:

  • 如果表包含多个关系,那么它会导致到数据库的多次往返。
【解决方案2】:

EF6 不可能,我认为 EF Core 不会改变这一点。这是因为Find 方法的主要目的是从本地缓存中获取已经加载的实体,或者如果它不存在则从数据库中加载它。所以急切加载(Include)只能在后一种情况下使用,而在前一种情况下需要执行显式加载。将两者结合在一个方法中在技术上可能是可行的,但很难。

我认为您应该采用结合预加载的FirstOrDefault(或SingleOrDefault)路线。您可以在Repository generic method GetById using eager loading 中查看 EF6 的示例实现。它可以针对 EF Core 进行调整,例如使用 dbContext.Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties 来查找 PK 属性并构建谓词。此外,由于 EF Core 包含更复杂一些(需要 Include / ThenInclude 链),您可能会发现此线程 Can a String based Include alternative be created in Entity Framework Core? 很有趣。

【讨论】:

    猜你喜欢
    • 2014-07-01
    • 2021-04-05
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    • 2023-04-02
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    相关资源
    最近更新 更多