cra*_*aig 4 c# linq entity-framework-core asp.net-core-2.0 entity-framework-core-2.1
我在SQL Server中创建了一个内联表值函数(ITVF),它返回一个值表(为了讨论的目的简化了查询):
CREATE FUNCTION dbo.VehicleRepairStatus()
RETURNS TABLE
AS
RETURN
SELECT VehicleID, CurrentStatus
FROM VehicleRepairHistory
...
Run Code Online (Sandbox Code Playgroud)
我可以在查询中引用:
SELECT
v.ID, v.Name,
r.CurrentStatus
FROM
Vehicle v
LEFT OUTER JOIN
dbo.VehicleRepairStatus() r on v.ID = r.VehicleID
Run Code Online (Sandbox Code Playgroud)
我希望能够在Linq查询中使用它:
var vehicles = await _databaseContext.Vehicles
.Join() // join ITVF here?
.Where(v => v.Type == 'Bus' )
.OrderBy(v => v.Name)
.ToAsyncList();
Run Code Online (Sandbox Code Playgroud)
在某些时候,我可能会更改ITVF以包含一个参数:
CREATE FUNCTION dbo.VehicleRepairStatus(@id AS INT)
RETURNS TABLE
AS
RETURN
SELECT VehicleID, CurrentStatus
FROM VehicleRepairHistory
...
WHERE VehicleID = @id
Run Code Online (Sandbox Code Playgroud)
并称之为标量:
SELECT v.ID, v.Name
,(SELECT val FROM dbo.VehicleRepairStatus(v.ID)) AS CurrentStatus
FROM Vehicle v
Run Code Online (Sandbox Code Playgroud)
Linq查询:
var vehicles = await _databaseContext.Vehicles
.Select( ) // call ITVF here?
.Where(v => v.Type == 'Bus' )
.OrderBy(v => v.Name)
.ToAsyncList();
Run Code Online (Sandbox Code Playgroud)
两种方法都可以吗?
是的,可以通过使用EF Core 2.1引入的查询类型来实现.以下是必需的步骤:
首先,创建一个类来保存TVF记录(使用正确的数据类型更新它):
public class VehicleRepairStatus
{
public int VehicleID { get; set; }
public int CurrentStatus { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后在您的注册中注册OnModelCreating
:
modelBuilder.Query<VehicleRepairStatus>();
Run Code Online (Sandbox Code Playgroud)
然后使用Query
和FromSql
方法的组合从db上下文中公开它:
public IQueryable<VehicleRepairStatus> VehicleRepairStatus(int id) =>
Query<VehicleRepairStatus>().FromSql($"select * from VehicleRepairStatus({id})");
Run Code Online (Sandbox Code Playgroud)
就这样.
现在,您可以像在任何其他IQueryable<T>
返回方法中一样在LINQ查询中使用它,例如:
from v in db.Vehicles
from r in db.VehicleRepairStatus(v.ID)
select new { v.ID, v.Name, r.CurrentStatus }
Run Code Online (Sandbox Code Playgroud)
"select"内部FromSql
方法使其可组合,因此整个查询被转换为SQL并执行服务器端.
更新:实际上,当用作上述示例的相关子查询时,这不起作用(请参阅参考ITVF引发"在上一个操作完成之前在此上下文上启动的第二个操作"异常).它只能在传递常量/变量参数时使用
from r in db.VehicleRepairStatus(123)
...
Run Code Online (Sandbox Code Playgroud)
请参阅链接中的后续帖子的答案,以便正确实施相关查询方案.
归档时间: |
|
查看次数: |
1220 次 |
最近记录: |