Skip to main content

Fixed: "The query uses the 'First'/'FirstOrDefault' operator without 'OrderBy' and filter operators" in EF Core

· 6 min read
Jagdish Kumawat
Founder @ Dewiride

FirstOrDefaultAsync() returned a row, and EF Core logged a warning with it: The query uses the 'First'/'FirstOrDefault' operator without 'OrderBy' and filter operators. This may lead to unpredictable results. The word "first" needs an order to mean anything, and SQL doesn't give you one by itself. An OrderBy or a Where makes the warning go away, and the answer reliable.

What I Was Doing​

An endpoint in a .NET 10 Web API read one category, with EF Core 10 and MySQL 9.7, and no conditions:

src/Dewiride.Inventory.Api/Program.cs (temporary endpoint)
app.MapGet("/demo/first-noorder", async (InventoryDbContext db) =>
{
var c = await db.Categories.FirstOrDefaultAsync();
return Results.Ok(c?.Name);
});

What I Expected​

The first category, the one with the lowest ID, without a warning.

What I Got​

The right-looking answer, and a warning:

Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

"Cables"
API log
warn: Microsoft.EntityFrameworkCore.Query[10103]
The query uses the 'First'/'FirstOrDefault' operator without 'OrderBy' and filter operators. This may lead to unpredictable results.
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT `c`.`Id`, `c`.`CreatedAtUtc`, `c`.`Name`
FROM `categories` AS `c`
LIMIT 1

A terminal with a 200 OK response with the category name Cables, and the API log with the warning The query uses the 'First'/'FirstOrDefault' operator without 'OrderBy' and filter operators, and a SELECT with LIMIT 1 and no ORDER BY.

What I Checked​

The SQL. LIMIT 1, with no ORDER BY and no WHERE. That asks MySQL for any one row.

Whether "any row" is really a risk. It is. On the products table, adding one column to a query with LIMIT 3 changed which rows came back, because MySQL chose a different way to read the table; the Skip and Take post shows it. EF Core's pagination page says "relational databases do not apply any ordering by default, even on the primary key."

When EF Core stays quiet. The warning needs both to be missing. With a Where on the key, there's nothing to choose from, so EF Core doesn't warn:

API log (FirstOrDefaultAsync with a Where on the Id)
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1ms) [Parameters=[@id='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `c`.`Id`, `c`.`CreatedAtUtc`, `c`.`Name`
FROM `categories` AS `c`
WHERE `c`.`Id` = @id
LIMIT 1

Why It Happens​

First means "the first row of the results". Results only have a first row if something sorts them or narrows them to one. Otherwise, the row you get depends on how the database happens to read the table that day. It's a warning and not an error because the query can still run, and EF Core can't tell whether "any row" is what you meant.

The Fix​

Say which row you mean. For the lowest ID, sort:

An endpoint that says which row is first
app.MapGet("/demo/first-ordered", async (InventoryDbContext db) =>
{
var c = await db.Categories.OrderBy(c => c.Id).FirstOrDefaultAsync();
return Results.Ok(c?.Name);
});

For one specific row, filter instead, as FirstOrDefaultAsync(c => c.Id == id) does.

After the Fix​

Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

"Cables"
API log
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT `c`.`Id`, `c`.`CreatedAtUtc`, `c`.`Name`
FROM `categories` AS `c`
ORDER BY `c`.`Id`
LIMIT 1

A terminal with a 200 OK response with the category name Cables, and the API log with a SELECT that has ORDER BY Id and LIMIT 1, and no warning.

Common Mistakes​

MistakeWhat happensDo this instead
Assuming "first" means the lowest IDIt holds until MySQL reads the table differentlySort by what you mean
Using First to check whether any row existsIt loads a whole row for nothingUse AnyAsync
Hiding the warning in the log configurationThe row can still changeAdd the sort or the filter
Using Single to silence itIt throws when there's more than one rowUse it only when one row is a rule

Troubleshooting​

SymptomLikely causeFix
warn: Microsoft.EntityFrameworkCore.Query[10103]First with no OrderBy and no WhereAdd one of them
A different row comes back than yesterdayNo OrderBySort by a unique column
The warning for Skip or Take insteadThe same idea for pagingSee that post
Sequence contains no elementsFirstAsync on an empty resultUse FirstOrDefaultAsync

FAQ​

Why doesn't a Where alone need an OrderBy?​

EF Core only warns when neither is there. A Where on a key can match one row at most. A Where on another column can match many, and then you should still sort, even though no warning appears.

Does it matter if the table has one row?​

Not today. A table with one row tends to get a second, and the code won't warn you then either.

Conclusion​

"The query uses the 'First'/'FirstOrDefault' operator without 'OrderBy' and filter operators" means EF Core sent LIMIT 1 with nothing to say which row. It worked, and it could return a different row later. Add OrderBy to say which is first, or Where to say which one you want.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.