The problem
I have a client application which loads a local data file. This data file specifies for each item the Type
and Version
.
From this file, I compile a list of Type
and Version
pairs.
var typeVersionSets = datafile.Select(item => new { Type = item.TypeId, Version = item.VersionId }).Distinct();
Note: there are more than these two fields, but for the sake of simplicity I just denote these two.
I also have a SQL Server which runs in the cloud. I need to get all records from a table which meet the value pairs (so the column values must match simultaneously).
I wrote this simple query which cannot be run by EF Core:
List<MyTableRow> MyResult = await dbContext.MyTable
.Where(dbItem => typeVersionSets.Contains(new { Type = dbItem.TypeId, Version = dbItem.VersionId }))
.ToListAsync();
I get the following runtime error:
One or more errors occurred. (The LINQ expression 'DbSet().Where(p => __MyTableRowTypeVersions_2.Contains(new { Type = p.TypeId, Version = p.VersionId }))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.)
TLDR some details
The MyTable
is huge and I cannot afford to download it every time and evaluate the LINQ expression on the client.
The number of typeVersionSets
is reasonably small (let's say 10 sets).
Of course, I can loop over typeVersionSets
like:
List<MyTableRow> MyResult = new List<MyTableRow>();
foreach (var set in typeVersionSets)
{
MyResult.AddRange(
await dbContext.MyTable
.Where(pp => pp.TypeId == set.Type && pp.VersionId == set.Version)
.ToListAsync()
);
}
However, this would require 10 database calls.
This code will be executed many times per user and by many users.
Is there a more efficient solution which would result in 1 database call per event without transferring a lot of unnecessary data to the client (or the server).
Some additional notes
I use:
- .NET (core) 5.0
- Entity Framework Core version 5.0.9.
In case it matters, I cannot migrate to EF Core 6 since this required a migration to .NET (core) 6.0 which raises a lot of issues which are out of my scope.
typeVersionSets
in this query. Use a string builder and a loop or is there some nicer way? – Lox