I am attempting to reference an Inline Table-Valued Function (ITVF) in a Linq query:
var results = await (
from v in _context.Vehicles
from r in _con
Sorry, my fault. The technique from the answer to your previous question is applicable for calling ITVF with constant/variable parameters, but not with correlated subqueries like in your case (and my wrong example).
The solution is to remove the ITVF parameter and extend the result to include that column as well (effectively turning it into parameterless view):
CREATE FUNCTION dbo.UnitRepairStatus()
RETURNS TABLE
AS
RETURN
SELECT u.UnitNumber, h.InRepair
FROM Schema2.Unit u
INNER JOIN Schema2.History h on u.ID = h.UnitID
Also remove the parameter from the context method
EF Core 2.x:
public IQueryable<UnitRepairStatus> UnitRepairStatus() =>
Query<UnitRepairStatus>().FromSql("SELECT * FROM UnitRepairStatus()");
EF Core 3.x:
public IQueryable<UnitRepairStatus> UnitRepairStatus() =>
Set<UnitRepairStatus>().FromSqlRaw("SELECT * FROM UnitRepairStatus()");
and change the LINQ query to use join:
var results = await (
from v in _context.Vehicles
join r in _context.UnitRepairStatus() on v.VehicleNumber equals r.UnitNumber // <---
orderby v.VehicleNumber
select new FooViewModel {
ID = v.ID,
VehicleNumber = v.VehicleNumber,
InRepair = Convert.ToBoolean(r.InRepair)
}
).ToListAsync();
Now it should translate and execute server side, and successfully get materialized at the client.
The problem with the original approach was that EF Core silently switched the query execution to client evaluation (hate that), and then hit its protection for executing multiple async operations on one and the same context.