包含在FromSqlRaw和EF Core 3.1中的存储过程中
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了包含在FromSqlRaw和EF Core 3.1中的存储过程中相关的知识,希望对你有一定的参考价值。
所以这是交易-我目前正在使用EF Core 3.1,并且假设我有一个实体:
public class Entity
{
public int Id { get; set; }
public int AnotherEntityId { get; set; }
public virtual AnotherEntity AnotherEntity { get; set; }
}
[当我以正常方式访问DbSet<Entity> Entities
时,将包含AnotherEntity像:
_context.Entities.Include(e => e.AnotherEntity)
这可行。为什么不呢?然后我去:
_context.Entities.FromSqlRaw("SELECT * FROM Entities").Include(e => e.AnotherEntity)
这也适用。两者都向我返回与AnotherEntity连接的对象的相同集合。然后,我使用一个存储过程,该存储过程由名为spGetEntities:
的相同查询SELECT * FROM Entities
组成。_context.Entities.FromSqlRaw("spGetEntities")
猜怎么着?这也有效。显然,它给了我相同的输出,但没有加入AnotherEntity。但是,如果我尝试像这样添加包括:
_context.Entities.FromSqlRaw("spGetEntities").Include(e => e.AnotherEntity)
我正在:
FromSqlRaw或FromSqlInterpolated用不可组合的SQL调用并在其上进行查询。考虑致电
AsEnumerable
在FromSqlRaw或FromSqlInterpolated方法之后执行客户端的组成。
即使_context.Entities.FromSqlRaw("SELECT * FROM Entities")
和_context.Entities.FromSqlRaw("spGetEntities")
的输出相同。
我找不到能或不能用EF Core 3.1做到的证明,但是如果有人可以给我任何暗示这种方法的可能性,那就太好了。
此外,如果还有另一种使用存储过程获取连接实体的方法,我可能会接受它作为我的问题的解决方案。
不久,您不能这样做(至少对于SqlServer)。解释包含在EF Core文档中-Raw SQL Queries-Composing with LINQ:
使用LINQ进行组合要求您的原始SQL查询必须是可组合的,因为EF Core会将提供的SQL视为子查询。可以组成的SQL查询以
SELECT
关键字开头。此外,传递的SQL不应包含对子查询无效的任何字符或选项,例如:
- 结尾的分号
- 在SQL Server上,尾随查询级提示(例如
OPTION (HASH JOIN)
)- 在SQL Server上,
ORDER BY
子句中的OFFSET 0 OR TOP 100 PERCENT
子句未与SELECT
一起使用SQL Server不允许通过存储过程调用进行组合,因此,任何尝试将附加查询运算符应用于此类调用的尝试都将导致无效的SQL。在
AsEnumerable
或AsAsyncEnumerable
方法之后立即使用FromSqlRaw
或FromSqlInterpolated
方法,以确保EF Core不会尝试对存储过程进行组合。
另外,由于Include
/ ThenInclude
需要EF Core IQueryable<>
,因此AsEnumerable
/ AsAsyncEnumerable
等不是选项。您确实需要可组合的SQL,因此无法选择存储过程。
但是,可以使用表值函数(TVF)或数据库视图来代替存储过程,因为它们是可组合的(select * from TVF(params)
或select * from db_view
)。
以上是关于包含在FromSqlRaw和EF Core 3.1中的存储过程中的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 FromSqlRaw 在 EF Core 3.0 中调用存储过程
如何使用 FromSqlRaw Entity Framework Core 3.1 从存储过程中返回多个 SELECT 集