在Linq和Entity Framework Core中使用内联表值函数

问题描述 投票:5回答:1

[我在SQL Server中创建了一个内联表值函数(ITVF),该函数返回一个值表(出于讨论目的简化查询):

CREATE FUNCTION dbo.VehicleRepairStatus()
RETURNS TABLE
AS
   RETURN
       SELECT VehicleID, CurrentStatus 
       FROM VehicleRepairHistory
       ...

我可以在查询中引用:

SELECT   
    v.ID, v.Name,
    r.CurrentStatus
FROM  
    Vehicle v
LEFT OUTER JOIN 
    dbo.VehicleRepairStatus() r on v.ID = r.VehicleID

我希望能够在Linq查询中使用它:

var vehicles = await _databaseContext.Vehicles
    .Join() // join ITVF here?
    .Where(v => v.Type == 'Bus' )
    .OrderBy(v => v.Name)
    .ToAsyncList();

[在某些时候,我可以更改ITVF以包括一个参数:

CREATE FUNCTION dbo.VehicleRepairStatus(@id AS INT)
RETURNS TABLE
AS
RETURN

  SELECT VehicleID, CurrentStatus 
  FROM   VehicleRepairHistory
  ...
  WHERE  VehicleID = @id

并且像标量一样调用:

SELECT   v.ID, v.Name
        ,(SELECT val FROM dbo.VehicleRepairStatus(v.ID)) AS CurrentStatus
FROM  Vehicle v

Linq查询:

var vehicles = await _databaseContext.Vehicles
    .Select( )  // call ITVF here?
    .Where(v => v.Type == 'Bus' )
    .OrderBy(v => v.Name)
    .ToAsyncList();

这两种方法都有可能吗?

c# linq entity-framework-core asp.net-core-2.0 entity-framework-core-2.1
1个回答
8
投票
是的,可以利用引入的EF Core 2.1 query types。以下是必需的步骤:

首先,创建一个类来保存TVF记录(使用正确的数据类型对其进行更新:]

public class VehicleRepairStatus { public int VehicleID { get; set; } public int CurrentStatus { get; set; } }

然后将其注册到您的OnModelCreating

modelBuilder.Query<VehicleRepairStatus>();

然后使用QueryFromSql方法的组合从数据库上下文中公开它:

public IQueryable<VehicleRepairStatus> VehicleRepairStatus(int id) => Query<VehicleRepairStatus>().FromSql($"select * from VehicleRepairStatus({id})");

仅此而已。 

现在,您可以像其他任何IQueryable<T>返回方法一样在LINQ查询中使用它,例如:

from v in db.Vehicles from r in db.VehicleRepairStatus(v.ID) select new { v.ID, v.Name, r.CurrentStatus }

FromSql方法内部的“选择”使其变为“ [可组合,因此整个查询将转换为SQL并在服务器端执行。

Update:实际上,如上例所示,当用作相关子查询时,这不起作用(请参见Reference to an ITVF raises a "second operation started on this context before a previous operation completed" exception)。仅当传递常量/变量参数,例如

时才可以使用它

from r in db.VehicleRepairStatus(123) ...

请参阅链接中后续帖子的答案,以获取相关查询方案的正确实现。
© www.soinside.com 2019 - 2024. All rights reserved.