'Can't process set operations after client evaluation efcore
Ef Core receiving error
System.InvalidOperationException: Can't process set operations after client evaluation, consider moving the operation before the last Select() call (see issue #16243) at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.ApplySetOperation(SetOperationType setOperationType, SelectExpression select2, Boolean distinct)
when executing
public async Task<object> GetUnitsForDataTableAsync() =>
await context.Units
.Where(x => !x.TractUnitJunctions.Any())
.Select(x => new
{
x.Id,
x.UnitName,
x.UnitAcres,
TractNum = String.Empty,
Wells = String.Empty,
NumOfWells = 0,
})
.Union(
context.TractUnitJunctions
.Select(x => new
{
Id = x.UnitId,
x.Unit.UnitName,
x.Unit.UnitAcres,
x.Tract.TractNum,
Wells = string.Join(", ", x.TractUnitJunctionWellJunctions
.Select(z => $"{z.Well.WellNum} ({z.Well.ApiNum})")
),
NumOfWells = x.TractUnitJunctionWellJunctions.Count()
}))
.ToListAsync().ConfigureAwait(false);
however the function works fine if I break it up into two queries.
public async Task<object> GetUnitsForDataTableAsync()
{
var List1 = await context.Units
.Where(x => !x.TractUnitJunctions.Any())
.Select(x => new
{
x.Id,
x.UnitName,
x.UnitAcres,
TractNum = String.Empty,
Wells = String.Empty,
NumOfWells = 0,
})
.ToListAsync().ConfigureAwait(false);
var List2 = await context.TractUnitJunctions
.Select(x => new
{
Id = x.UnitId,
x.Unit.UnitName,
x.Unit.UnitAcres,
x.Tract.TractNum,
Wells = string.Join(", ", x.TractUnitJunctionWellJunctions
.Select(z => $"{z.Well.WellNum} ({z.Well.ApiNum})")
),
NumOfWells = x.TractUnitJunctionWellJunctions.Count()
})
.ToListAsync().ConfigureAwait(false);
return List1.Concat(List2);
}
I've researched that error a bit but I'm unsure how to refactor the first query to get around that error
Solution 1:[1]
Accepted answer while it works is flawed in that you're eager loading the first list.
This is a known bug which you should be able to resolve by moving the Where clause after the Union
As discussed here https://github.com/dotnet/efcore/issues/16243#issuecomment-622452276
Solution 2:[2]
This is a limitation of EF Core and I don't think it will be resolved ever. First list is easily translatable to the SQL, but second list is eager loading query with client side evaluation part and you cannot use it with Concat function. So you have to run two queries and make union on the client side.
Anyway this query can be easily written by the SQL (depends on dialect) without Concat and eager loading. Or via LINQ with appropriate extension (will provide solution on request)
Solution 3:[3]
Using LINQ to SQL let keyword
Today, I also encountered such a problem, which was solved in this way!
You can try changing it like this:
(from u in context.Units
let TractNum= String.Empty
let Wells = String.Empty
let NumOfWells = 0
select new
{
u.Id,
u.UnitName,
u.UnitAcres,
TractNum
Wells
NumOfWells
}).union(
from u in context.Units
let TractNum= String.Empty
let Wells = String.Empty
let NumOfWells = 0
select new
{
u.Id,
u.UnitName,
u.UnitAcres,
TractNum
Wells
NumOfWells
}
)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | stuartdotnet |
| Solution 2 | |
| Solution 3 | ouflak |
