【问题标题】:How to call a stored procedure in EF Core 3.0 via FromSqlRaw如何通过 FromSqlRaw 在 EF Core 3.0 中调用存储过程
【发布时间】:2019-10-02 18:19:12
【问题描述】:

我最近从 EF Core 2.2 迁移到 EF Core 3.0。

不幸的是,我还没有找到一种方法来调用返回实体的存储过程。

在 EF Core 2.0 中是可能的:

var spParams = new object[] { "bla", "xx" };
var createdPath = ModelContext.Paths.FromSql("AddNodeWithPathProc  @p0, @p1", spParams).Single();

在 EF Core 3.0 中,方法 FromSQL 被替换为 FromSqlRaw。但是,我没有设法成功调用存储过程然后处理该值。这在存储过程将数据插入数据库时​​很有用。

所以在 EF Core 3.0 中,我使用以下代码:

var createdPath = ModelContext.Paths.FromSqlRaw("AddNodeWithPathProc @p0, @p1", spParams).Single();

但它会抛出异常,因为生成的 SQL 是无效的,看起来像这样:

exec sp_executesql N'SELECT TOP(2) [p].[PathId], [p].[Level], [p].[NodeId], [p].[NodePath], [p].[NodePathString]
FROM (
     @sql @p0, @p1
) AS [p]',N'@p0 nvarchar(4000),@p1 nvarchar(4000), @sql nvarchar(100)',@p0=N'1a',@p1=N'', @sql=N'AddNodeWithPathProc'

我尝试了很多变体,但都没有成功。

我开始认为不可能使用ModelContext.[IQueryable].FromSqlRaw 运行存储过程。在我看来,这种方法打败了FromSqlRaw 的主要原因之一,因为对于普通的选择语句,LINQ 通常足够好。

有谁知道如何在 EF Core 3.0 中结合使用存储过程和 FromSqlRaw?非常感谢任何帮助。

提前致谢

PS:我知道您可以使用this.Database.ExecuteSqlRaw(SQL, parameters) 执行存储过程。但是,这样就无法检索存储过程查询的任何实体。

【问题讨论】:

  • 尝试 .ToList() 而不是 .Single()。 .Single() 正在生成“TOP(2)”包装器。
  • 我暂时的解决方法如下:this.ModelContext.ExecuteRawSql("EXEC AddNodeWithPathProc @p0, @p1", spParams); var createdPath = ModelContext.Paths.FromSqlRaw("SELECT TOP 1 * FROM dbo.Path ORDER BY PathID DESC").Single();但是,这不是一个可接受的生产解决方案。
  • 是的.. ToList() 有效.. 非常感谢 :-)

标签: c# entity-framework entity-framework-core .net-core-3.0


【解决方案1】:

解决方案(感谢 David Browne,您应该将其发布为答案):

用 ToList 替换 Single 可以:-)

var createdPath = ModelContext.Paths.FromSqlRaw("AddNodeWithPathProc  {0}, {1}", nodeTitle, parentPathString).ToList();

【讨论】:

    【解决方案2】:

    这非常奇怪……就在几天前,我遇到了同样的问题并关注了这篇文章。我接到了这个电话:

     public IEnumerable<TableChange> GetTableLastChanges(string tableName, string keyColumn, out int synchronizationVersion)
        {
            var parameters = new[] {
                new SqlParameter("@table_name", SqlDbType.VarChar) { Direction = ParameterDirection.Input, Value = tableName },
                new SqlParameter("@key_column", SqlDbType.VarChar) { Direction = ParameterDirection.Input, Value = keyColumn },
                new SqlParameter("@synchronization_version", SqlDbType.BigInt) { Direction = ParameterDirection.InputOutput, Value = 0 }
            };
    
            var changes = this.TableChanges.FromSqlRaw("[dbo].[GetTableLastChanges] @table_name, @key_column, @synchronization_version OUTPUT", parameters).ToList();
    
            synchronizationVersion = Convert.ToInt32(parameters[2].Value);
    
            return changes;
        }
    

    现在一切正常,此调用按预期工作。因此,我应该承认 Core 3 上 EF 的数据集和参数返回没有问题。

    【讨论】:

      【解决方案3】:
      var result=context.yourmodelclass.FromSqlInterpolated($"StoredProcedureName {param1},{param2}").tolist();
      

      如果需要,您可以添加多个参数。 注意:

      • context => 您的数据库名称。
      • yourmodelclass=> 您创建的模型文件夹中的类,用于从存储过程结果中获取输出结果。

      【讨论】:

        【解决方案4】:

        我不在我可以测试的地方,但我认为以下方法会起作用:

        var createdPath = ModelContext.Paths.FromSqlRaw("AddNodeWithPathProc {0}, {1}", parm1 parm2).Single();
        

        【讨论】:

        • 不,这不起作用。刚刚测试过了。无效的 sql :-(。我相信它与生成的 sql 有关。如果我用探查器检查 sql,它总是遵循模式:sp_executesql 'SELECT * FROM {mySqlPassedInMethod}。我不会知道如何在此代码中传递存储过程.因此.net方法检测到传递的sql字符串用于存储过程并相应地调整生成的sql,或者在T-SQL中有一种我不知道的方法知道(我不是专家)
        【解决方案5】:

        尝试分离SqlParameter:

        SqlParameter param1 = new SqlParameter("@p0","value");
        SqlParameter param2 = new SqlParameter("@p1","value");
        
        var createdPath = ModelContext.Paths.FromSqlRaw("AddNodeWithPathProc @p0 @p1", param1, 
        param2).Single();
        

        【讨论】:

        • 在下方为您删除的帖子发布了解决方案。
        • 刚试了一下,失败了:-(。错误是:“System.InvalidCastException: 'SqlParameterCollection 只接受非空SqlParameter 类型对象,不接受SqlParameter 对象。'”。没有sql发送到 sql server(根据 sql profiler)
        • @jdweng 非常感谢 :) 当我登录到我的软件并下载最后更新的 XML 文件时,我有这个解决方案,但我需要所有历史数据而不会丢失。所以我有另一种选择来设置日期并下载带有费率的 excel 文件,但我不知道如何实现。在服务器上运行服务?也许用户一周不使用软件,所以我错过了整整一周的汇率。
        • @ISTech :查看以下页面:boi.org.il/en/Markets/Pages/explainxml.aspx 您可以在 url 中添加日期。 boi.org.il/currency.xml?rdate=20120101
        • @ISTech :我更新了下面的代码来做一个日期范围。
        【解决方案6】:

        看看这里:

        https://github.com/DarioN1/SPToCore

        这是一个存储过程的脚手架,它可以帮助你使用sp。

        它不是第三方库,它生成纯 c# 代码以包含在您的项目中,扩展当前 dbContext 以提供存储过程方法、参数映射和分类结果。

        【讨论】:

          猜你喜欢
          • 2021-10-13
          • 2020-04-10
          • 1970-01-01
          • 1970-01-01
          • 2020-11-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多