如何使用 FromSqlRaw Entity Framework Core 3.1 从存储过程中返回多个 SELECT 集

Posted

技术标签:

【中文标题】如何使用 FromSqlRaw Entity Framework Core 3.1 从存储过程中返回多个 SELECT 集【英文标题】:How to return multiple SELECT sets from a stored procedure using FromSqlRaw Entity Framework Core 3.1 【发布时间】:2021-09-10 04:43:17 【问题描述】:

我目前在从数据库返回值时遇到问题,我正在使用 SQL Server 存储过程和 ASP.NET Core 3.1 来检索多个 SELECT 集。

这是我的存储过程:

ALTER PROCEDURE [dbo].[MyProc]
    @BusinessModelID int
AS
BEGIN
    SELECT Id, Title 
    FROM [dbo].[Channels] 
    WHERE BusinessModelId = @BusinessModelID;

    SELECT Id, Title 
    FROM [dbo].[Problems] 
    WHERE BusinessModelId = @BusinessModelID;

    SELECT Id, Title 
    FROM [dbo].[CostStructures] 
    WHERE BusinessModelId = @BusinessModelID;

    SELECT Id, Title 
    FROM [dbo].[CustomerSegments] 
    WHERE BusinessModelId = @BusinessModelID;

    SELECT Id, Title 
    FROM [dbo].[KeyMetrics] 
    WHERE BusinessModelId = @BusinessModelID;

    SELECT Id, Title 
    FROM [dbo].[RevenueStreams] 
    WHERE BusinessModelId = @BusinessModelID;

    SELECT Id, Title 
    FROM [dbo].[Solutions] 
    WHERE BusinessModelId = @BusinessModelID;

    SELECT Id, Title 
    FROM [dbo].[Unfairs] 
    WHERE BusinessModelId = @BusinessModelID;

    SELECT Id, Title 
    FROM [dbo].[Values] 
    WHERE BusinessModelId = @BusinessModelID;
END

这是我的 C# 代码:

var modelList = _dataContext.Set<BusinessToGet>()
                        .FromSqlRaw($"EXECUTE MyProc @BusinessModelID=businessModelId")
                        .ToList();

问题是它应该返回多个集合,但它只返回一个通道。我做错了什么?

提前致谢。

【问题讨论】:

【参考方案1】:

更新

在这种情况下,表之间存在重复的主键。尽管下面的 SQL 在 SQL-server 中运行良好,但 EF Core 返回了许多重复实例,因为当 EF Core 看到 Id = 1 的实例时,它会将其用于 Id = 1 的所有后续实例。

解决方法是使用无密钥 DTO 进行 FromSqlRaw 查询。

[Keyless]
public class BlogPostsCount

Id, 
    public int Id  get; set; 
    public string Title  get; set; 

https://docs.microsoft.com/en-us/ef/core/modeling/keyless-entity-types?tabs=data-annotations


使用 UNION 应该可以解决这个问题。如果表之间的数据类型不同,您可能还需要转换列值以产生统一的结果。如果您有跨表重复,并且需要全部,请使用 UNION ALL

SELECT Id, Title FROM [dbo].[Channels] WHERE BusinessModelId = @BusinessModelID
UNION
SELECT Id,Title FROM [dbo].[Problems] WHERE BusinessModelId = @BusinessModelID
UNION
SELECT Id, Title FROM [dbo].[CostStructures] WHERE BusinessModelId = @BusinessModelID
UNION
SELECT Id, Title FROM [dbo].[CustomerSegments] WHERE BusinessModelId = @BusinessModelID
UNION
SELECT Id, Title FROM [dbo].[KeyMetrics] WHERE BusinessModelId = @BusinessModelID
UNION
SELECT Id, Title FROM [dbo].[RevenueStreams] WHERE BusinessModelId = @BusinessModelID
UNION
SELECT Id, Title FROM [dbo].[Solutions] WHERE BusinessModelId = @BusinessModelID
UNION
SELECT Id, Title FROM [dbo].[Unfairs] WHERE BusinessModelId = @BusinessModelID
UNION
SELECT Id, Title FROM [dbo].[Values] WHERE BusinessModelId = @BusinessModelID

【讨论】:

我尝试使用 UNION ALL,但它似乎仍然返回重复项,它返回正确的行数,但在到达 C# 代码时返回正确的数据。 :( @RodolfoA.Calvo:UNION ALL 将返回重复项(如果有)。 UNION 执行隐式select distinct。您能否更具体地说明您遇到的问题? BR 当然!您的解决方案在 SQL Server 中完美运行,但是现在当我调试我的 C# 代码时,数据只带有一个重复的结果,但数字正确,例如:在 SQL 中,结果是 1 - 我的频道 1 - 我的问题 1-成本结构......等等,这是正确的,但在 C# 中,结果是 1 - 我的频道 1 - 我的频道 1 - 我的频道 1 - 我的频道 1 - 我的频道。我在 SQL SP SELECT DISTINCT * FROM [dbo].[Channels] WHERE BusinessModelId = @BusinessModelID UNION ALL 中为所有这些人做了这个 我认为您也必须添加 TableName 属性才能知道谁是谁。并添加到每个选择查询“'Chanels' as a TableName”例如 @Serge:我正在研究这个似乎没有任何注释的相关问题:github.com/dotnet/efcore/issues/24078BR

以上是关于如何使用 FromSqlRaw Entity Framework Core 3.1 从存储过程中返回多个 SELECT 集的主要内容,如果未能解决你的问题,请参考以下文章

如何在 EF.core 中使用 FromSqlRaw 指定列

如何将参数传递给 FromSqlRaw?

如何在 c# 实体框架核心中使用 FromSqlRaw() 将 OUTPUT 参数发送到 MySql 存储过程

如何通过 FromSqlRaw 在 EF Core 3.0 中调用存储过程

解决org.hibernate.HibernateException: identifier of an instance of com.ahd.entity.Order was altered fr

使用 EF 生成的 MySQL 在 LinQ 中为 FromSqlRaw 在从系统中选择变量时返回“SQL 语法错误”