【发布时间】: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() 所做的那样,也许?。
【问题讨论】:
-
它们都是非常不同的东西,并且在所有文档中都有详细说明。关于这个问题有几个重复,网上也有很多信息。
First和Single将始终命中数据库,Find不会。First和Single也做不同的事情。根据是否只有一条记录,可能不止一条,或者您不介意将其缓存在上下文中,您选择哪一个应该非常明显 -
对正在执行的 SQL 进行数据库跟踪。作为一般规则,
FirstOrDefault将执行TOP 1和SingleOrDefault将执行TOP 2(即稍微慢一些)。
标签: c# linq ef-core-2.0