We have 3 different approaches to get single items from EFCore they are FirstOrDefaultAsync()
, SingleOrDefaultAsync()
(including its versions with not default value returned, also we have FindAsync()
and maybe more with the same purpose like 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);
I would like to know the differences between each one of them. So far what I know is that we FirstOrDefaultAsync()
to get the first given a condition, (usually using this because we know that more than one item can satisfy the condition), on the other hand we use SingleOrDefaultAsync()
because we know that there is only one possible match to find, and FindAsync()
to get an item given its primary key.
I think FirstOrDefaultAsync()
& SingleOrDefaultAsync()
always hit the database (not sure about this), and FindAsync()
this is what Microsoft docs says:
Asynchronously finds an entity with the given primary key values. If an entity with the given primary key values exists in the context, then it is returned immediately without making a request to the store. Otherwise, a request is made to the store for an entity with the given primary key values and this entity, if found, is attached to the context and returned. If no entity is found in the context or the store, then null is returned.
So my question is, if our given condition used for FirstOrDefault()
, SingleOrDefault()
and FindAsync()
is the primary key, do we have any actual difference?
What I think is that the first time they are used always hit the db, but what about the next calls?. And probably EFCore could use the same context to get the values for FirstOrDefault()
and SingleOrDefault()
as it does for FindAsync()
, maybe?.
FindAsync
In much of the scaffolded code, FindAsync can be used in place of FirstOrDefaultAsync.
SingleOrDefaultAsync
fetches more data and does unnecessary work. throws an exception if there's more than one entity that fits the filter part.
FirstOrDefaultAsync
doesn't throw if there's more than one entity that fits the filter part.