Skip to main content

How to Find Rows by a List of IDs with Contains in EF Core

· 4 min read
Jagdish Kumawat
Founder @ Dewiride

To load several rows by their IDs, call Contains on the list inside your Where. It reads backwards the first time, and EF Core turns it into a plain SQL IN. An empty list is worth seeing too: it doesn't fail, and it doesn't return everything.

Prerequisites​

  • A .NET C# project using EF Core. I used EF Core 10.0.14 and MySQL 9.7.4.

Step 1: Write the Query​

An endpoint
g.MapGet("/contains", async ([FromQuery] int[] ids, InventoryDbContext db, CancellationToken cancellationToken) =>
{
var products = await db.Products
.Where(p => ids.Contains(p.Id))
.OrderBy(p => p.Id)
.Select(p => new { p.Id, p.Sku })
.ToListAsync(cancellationToken);

return Results.Ok(products);
});

The endpoint in a macOS-style code window, with a FromQuery int array parameter and a Where that calls ids.Contains on the product's Id.

[FromQuery] int[] ids reads the same parameter repeated in the query string.

Step 2: Call It​

Request
GET http://localhost:5190/demo/contains?ids=1&ids=2&ids=3
Output
[
{
"id": 1,
"sku": "CBL-USBC-2M"
},
{
"id": 2,
"sku": "CBL-USBC-1M"
},
{
"id": 3,
"sku": "CBL-HDMI-2M"
}
]

Step 3: See the SQL​

API log
Executed DbCommand (1ms) [Parameters=[@ids1='?' (DbType = Int32), @ids2='?' (DbType = Int32), @ids3='?' (DbType = Int32)], CommandType='Text', CommandTimeout='0']
SELECT `p`.`Id`, `p`.`Sku`
FROM `products` AS `p`
WHERE `p`.`Id` IN (@ids1, @ids2, @ids3)
ORDER BY `p`.`Id`

The log showing a SELECT with WHERE p.Id IN (@ids1, @ids2, @ids3).

Each value gets its own parameter, so a user's input never becomes part of the SQL.

Step 4: Try an Empty List​

With no ids at all, here's what MySQL received, on the second line:

Output (MySQL's log)
+-------------------------------------------------------------------------------------------------+
| statement |
+-------------------------------------------------------------------------------------------------+
| SELECT `p`.`Id`, `p`.`Sku` FROM `products` AS `p` WHERE `p`.`Id` IN (1, 2, 3) ORDER BY `p`.`Id` |
| SELECT `p`.`Id`, `p`.`Sku` FROM `products` AS `p` WHERE FALSE ORDER BY `p`.`Id` |
+-------------------------------------------------------------------------------------------------+

WHERE FALSE returns nothing, which is the right answer for "these zero IDs".

Common Mistakes​

MistakeWhat happensDo this instead
Loading rows one at a time in a loopOne query per IDUse Contains
Sending thousands of IDsA very long statementSplit them into batches
Assuming the results come back in your orderSQL doesn't promise anyAdd OrderBy, or sort in C#

Troubleshooting​

SymptomLikely causeFix
ids is empty though it's in the URLThe parameter's name differs?ids=1&ids=2, matching the name
A 400 for a listA value isn't a numberFailed to bind parameter
It's slowNo index on the columnAdd one, or use the primary key

Conclusion​

Write ids.Contains(p.Id) in your Where, and EF Core sends IN, with one parameter per value. An empty list sends WHERE FALSE.

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.