我们有三种不同的方法来从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()
是根据 Microsoft 文档的说法:
异步查找具有给定主键值的实体。如果存在具有给定主键值的实体,则立即返回该实体,而不对存储进行请求。否则,将向存储发出请求以获取具有给定主键值的实体,并将找到的该实体连接到上下文并返回。如果在上下文或存储中没有找到实体,则返回 null。
那么我的问题是,如果我们用于 FirstOrDefault()
、SingleOrDefault()
和 FindAsync()
的给定条件是主键,我们是否有任何实际的差别?
我认为它们第一次使用总是会与数据库交互,但是下一次呢? 也许 EFCore 可以使用相同的上下文获取 FirstOrDefault()
和 SingleOrDefault()
的值,就像它对 FindAsync()
做的那样,也许?
First
和Single
总是会访问数据库,而Find
则不会。此外,First
和Single
也有不同的功能。你应该根据是否只有一个记录、可能有多个记录或者你不介意它被缓存在上下文中来选择其中之一,这应该非常明显。 - TheGeneralFirstOrDefault
将会执行TOP 1
,而SingleOrDefault
将会执行TOP 2
(即稍微慢一些)。 - mjwills