【问题标题】:FirstOrDefaultAsync() & SingleOrDefaultAsync() vs FindAsync() EFCoreFirstOrDefaultAsync() & SingleOrDefaultAsync() vs FindAsync() EFCore
【发布时间】:2019-02-22 03:37:42
【问题描述】:

我们有 3 种不同的方法从 EFCore 获取单个项目,它们是 FirstOrDefaultAsync()SingleOrDefaultAsync()(包括不返回默认值的版本,我们还有 FindAsync() 以及可能更多具有相同目的的方法,例如 LastOrDefaultAsync() .

     var findItem = await dbContext.TodoItems
       .FindAsync(request.Id)
       .ConfigureAwait(false);

     var firstItem = await dbContext.TodoItems
        .FirstOrDefaultAsync(i => i.Id == request.Id)
        .ConfigureAwait(false);

     var singleItem = await dbContext.TodoItems
        .SingleOrDefaultAsync(i => i.Id == request.Id)
        .ConfigureAwait(false);

我想知道它们之间的区别。到目前为止,我所知道的是我们FirstOrDefaultAsync() 得到第一个给定的条件,(通常使用这个,因为我们知道不止一个项目可以满足条件),另一方面我们使用SingleOrDefaultAsync() 因为我们知道只能找到一个可能的匹配项,FindAsync() 可以在给定主键的情况下获取项目。

我认为FirstOrDefaultAsync()SingleOrDefaultAsync() 总是会访问数据库(对此不确定),而FindAsync() 这是微软文档所说的:

异步查找具有给定主键值的实体。如果 具有给定主键值的实体存在于上下文中, 然后立即返回而不向商店提出请求。 否则,将向商店请求具有给定实体的实体 主键值和该实体(如果找到)附加到 上下文并返回。如果在上下文中找不到实体或 store,则返回null。

所以我的问题是,如果我们用于FirstOrDefault()SingleOrDefault()FindAsync() 的给定条件是主键,我们有什么实际区别吗?

我认为第一次使用它们总是会命中数据库,但是下一次调用呢?。并且可能 EFCore 可以使用相同的上下文来获取 FirstOrDefault()SingleOrDefault() 的值,就像它为 FindAsync() 所做的那样,也许?

【问题讨论】:

  • 它们都是非常不同的东西,并且在所有文档中都有详细说明。关于这个问题有几个重复,网上也有很多信息。 FirstSingle 将始终命中数据库,Find 不会。 FirstSingle 也做不同的事情。根据是否只有一条记录,可能不止一条,或者您不介意将其缓存在上下文中,您选择哪一个应该非常明显
  • 对正在执行的 SQL 进行数据库跟踪。作为一般规则,FirstOrDefault 将执行 TOP 1SingleOrDefault 将执行 TOP 2(即稍微慢一些)。
  • github.com/aspnet/Docs/issues/4737 可能值得一读。

标签: c# linq ef-core-2.0


【解决方案1】:

查找异步

在许多脚手架代码中,可以使用 FindAsync 代替 FirstOrDefaultAsync。

SingleOrDefaultAsync

获取更多数据并做不必要的工作。如果抛出异常 有多个实体适合过滤器部分。

FirstOrDefaultAsync

如果有多个实体适合过滤器,则不会抛出 部分。

https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/crud?view=aspnetcore-2.2#singleordefaultasync-vs-firstordefaultasync

【讨论】:

  • 这正是我要找的,但很难找到,因为它在 Razor Pages 的另一篇文章中。
【解决方案2】:

FindAsync:

  • 接受主键
  • 针对查找具有主键的实体进行了优化,通过返回 如果实体被跟踪,实体不会访问数据库。
  • 不能将 include 方法与 FindAsync 一起使用。
  • 如果未找到匹配项,则返回默认值。

FirstOrDefaultAsync:

  • 接受表达式。
  • 如果需要相关实体,最好选择 FindAsync。
  • 如果未找到匹配项,则返回默认值。

SingleOrDefaultAsync:

  • 接受表达式。
  • 如果未找到匹配项,则返回默认值。
  • 如果找到多个匹配项,则引发异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 2017-09-08
    • 2013-12-21
    • 1970-01-01
    • 2014-05-06
    相关资源
    最近更新 更多