【问题标题】:use stored procedure with EFCore5.0 error System.InvalidOperationException使用带有 EFCore5.0 错误 System.InvalidOperationException 的存储过程
【发布时间】:2021-09-13 06:49:48
【问题描述】:

我正在使用最新的 EF.core 版本 (5.0.7) 并尝试通过存储过程检索实体。 尝试了以下方法:

 //attemp 1
 res = _context.Entity.FromSqlRaw($"exec dbo.ProcedureName");
 //attemp 2
 res = _context.Entity.FromSqlRaw("exec ProcedureName", new SqlParameter("@ParamName", paramValue));
 //attemp 3
 res = _context.Entity.FromSqlRaw($"exec ProcedureName {paramValue}");
 //attemp 4
 res = _context.Entity.FromSqlInterpolated($"exec ProcedureName @ParamName = {paramValue}");
 //attemp 5
 res = _context.Entity.FromSqlInterpolated($"exec ProcedureName {paramValue}");

所有示例,不带“exec”,带和不带“@”的参数名称以及带和不带前导“dbo”的过程名称 我不断收到错误消息“System.InvalidOperationException:FromSqlRaw 或 FromSqlInterpolated 是使用不可组合的 SQL 调用的,并在其上进行了查询。考虑在 FromSqlRaw 或 FromSqlInterpolated 方法之后调用 AsEnumerable 以在客户端执行组合。” 我做错了什么?

附言

客户端组合不是一个选项。

该过程在 SSMS 中运行良好。

another thread 中声称这是 EF5.0 解决的问题,但显然不是。

【问题讨论】:

  • select * from (exec ...)包装存储过程调用
  • 修复了不同的问题。无法在 SqlServer 中编写 SP(尝试在 SQL 中编写,您会看到)。用 TVF 替换 SP 是唯一的选择。
  • select * from (exec ...) 在 SSMS 中的语法不正确,并在 C# 中抛出“语法错误”的“SqlException”
  • 在 SP SELECT TOP 1 * FROM (exec ProcedureName) 上作曲的示例。这不是有效的 SQL 查询。所以你需要打电话给FromSqlRaw(...).AsEnumerable()
  • 谢谢@FireAlkazar,但这不是我正在做的事情吗?或者可能是因为我使用 `_context.Entity` 来运行这个 SP,它会自动用“SELECT”包围它?

标签: c# entity-framework-core


【解决方案1】:

为了使用FromSqlRaw,你需要让做插值,它会把它转换成参数。 不要自己动手。

res = _context.Entity
  .FromSqlRaw("exec ProcedureName @ParamName = {paramValue}", paramvalue)
  .AsEnumerable();

请注意缺少$。还需要添加AsEnumerableto prevent it from trying to compose it

【讨论】:

  • FromSqlInterpolated 仅接受一个“FormatedString”类型的参数,因此您的代码无法编译
  • @Elizur 你说得对,我的意思是FromSqlRaw。并且你需要添加AsEnumerable
  • 没有这样的运气。我仍然得到与以前完全相同的错误。此外 - AsEnumerable() 正试图将其转换为客户端组合(通过 Linq 过滤),这是不可能的。但是你是什么意思 = {paramValue}" 我猜你的意思是 = {0}" (就像在旧的 String.Format() 中)
【解决方案2】:

实体框架throws the exception 阻止服务器端组合,除非查询以“SELECT”开头。

if (char.ToLowerInvariant(c) == 's'
    && char.ToLowerInvariant(NextChar()) == 'e'
    && char.ToLowerInvariant(NextChar()) == 'l'
    && char.ToLowerInvariant(NextChar()) == 'e'
    && char.ToLowerInvariant(NextChar()) == 'c'
    && char.ToLowerInvariant(NextChar()) == 't')
{
    var (c1, c2) = (NextChar(), NextChar());
    if (char.IsWhiteSpace(c1)
        || c1 == '-' && c2 == '-'
        || c1 == '/' && c2 == '*')
    {
        return;
    }
}

throw new InvalidOperationException(RelationalStrings.FromSqlNonComposable);

您特别提到“客户端组合不是一个选项”,但作为Ivan Stoev commented,SQL Server 不支持对存储过程的组合。如果可以在没有修改数据库状态的副作用的情况下,建议将其重写为表值函数。

有一个whole pile of issues 与FromSql 和mapping 有关,其中一些参考构成。我相信this one 表明 EF5.0 仅解决了根表每个层次结构实体的“不可组合”异常。

【讨论】:

    猜你喜欢
    • 2020-11-23
    • 1970-01-01
    • 2013-12-10
    • 2012-11-06
    • 2020-01-14
    • 1970-01-01
    • 2016-08-20
    • 2020-02-29
    • 1970-01-01
    相关资源
    最近更新 更多