C# FirstOrDefaultAsync()&;SingleOrDefaultAsync()与FindAsync()EFCore

C# FirstOrDefaultAsync()&;SingleOrDefaultAsync()与FindAsync()EFCore,c#,linq,ef-core-2.0,C#,Linq,Ef Core 2.0,我们有3种不同的方法从EFCore获取单个项目,它们是FirstOrDefaultAsync(),SingleOrDefaultAsync()(包括未返回默认值的版本,我们还有FindAsync(),可能还有更多类似于LastOrDefaultAsync()的方法 我想知道它们之间的区别。到目前为止,我所知道的是,我们使用FirstOrDefaultAsync()来获得给定条件的第一个(通常使用这个,因为我们知道不止一个项可以满足条件),另一方面,我们使用SingleOrDefaultAsync

我们有3种不同的方法从EFCore获取单个项目,它们是
FirstOrDefaultAsync()
SingleOrDefaultAsync()
(包括未返回默认值的版本,我们还有
FindAsync()
,可能还有更多类似于
LastOrDefaultAsync()
的方法

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

我认为
FirstOrDefaultAsync()
SingleOrDefaultAsync()
总是会命中数据库(对此不确定),而
FindAsync()
这就是Microsoft文档中所说的:

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

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

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

在大多数框架代码中,FindAsync可以用来代替 FirstOrDefaultAsync

SingleOrDefaultAsync

获取更多数据并执行不必要的工作。如果 有多个实体适合过滤器部件

FirstOrDefaultAsync

如果有多个实体符合筛选器,则不会抛出 部分


它们都是非常不同的东西,在所有文档中都有详细说明。关于这个问题有好几处重复,网上也有很多信息。
First
Single
总是会影响数据库,
Find
不会。同样
First
Single
也会做不同的事情。W您选择哪一个应该是非常明显的,这取决于是否只有一条记录,可能不止一条,或者如果您不介意将其缓存在上下文中,请对正在执行的SQL进行数据库跟踪。一般来说,
FirstOrDefault
将执行
TOP 1
,而
SingleOrDefault
将执行
TOP 2(即稍微慢一点)。可能值得一读。这正是我要找的,但很难找到,因为它在另一篇关于Razor页面的文章中。
     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);