Yes, it's possible by utilizing the EF Core 2.1 introduced query types (starting from EF Core 3.0, consolidated with entity types and now called keyless entity types). Following are the required steps:
First, create a class to hold the TVF record (update it with the correct data types):
public class VehicleRepairStatus
{
public int VehicleID { get; set; }
public int CurrentStatus { get; set; }
}
Then register it in your OnModelCreating
:
EF Core 2.x:
modelBuilder.Query<VehicleRepairStatus>();
EF Core 3.x:
modelBuilder.Entity<VehicleRepairStatus>().HasNoKey().ToView(null);
Then expose it from your db context using a combination of Query
and FromSql
methods (EF Core 2.x):
public IQueryable<VehicleRepairStatus> VehicleRepairStatus(int id) =>
Query<VehicleRepairStatus>().FromSql($"select * from VehicleRepairStatus({id})");
or Set
and FromSqlInterpolated
(EF Core 3.x):
public IQueryable<VehicleRepairStatus> VehicleRepairStatus(int id) =>
Set<VehicleRepairStatus>().FromSqlInterpolated($"select * from VehicleRepairStatus({id})");
And that's all.
Now you can use it inside your LINQ queries like any other IQueryable<T>
returning method, for instance:
from v in db.Vehicles
from r in db.VehicleRepairStatus(v.ID)
select new { v.ID, v.Name, r.CurrentStatus }
The "select" inside FromSql
method makes it composable, so the whole query is translated to SQL and executed server side.
Update: Actually this doesn't work when used as correlated subquery like the above example (see Reference to an ITVF raises a "second operation started on this context before a previous operation completed" exception). It could be used only if passing constant/variable parameters like
from r in db.VehicleRepairStatus(123)
...
See the answer to the follow up post from the link for correct implementation for correlated query scenarios.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…