【问题标题】:How to get Multiple OUTPUT parameters from stored procedure EF Core 3.1如何从存储过程 EF Core 3.1 中获取多个 OUTPUT 参数
【发布时间】:2021-01-27 02:05:05
【问题描述】:

我一直在尝试修改接受的答案here,这似乎利用了RelationalDataReader,以便从产品所有者希望尽可能多地由数据库驱动的 API 中获取一些计算日期的 2 个 OUTPUT 参数.

我有一个存储过程,可以根据我存储在表中的 SQL 查询计算开始日期和结束日期,因此添加另一个日期范围所需要做的就是将其添加到表中,其余的将就位在 UI 和管道的其余部分上。

RDFacadeExtensions 类的第一部分是相同的,但我认为我可以简单地添加更多参数并将它们取回,但我似乎遗漏了一些东西。

var ID = new SqlParameter("ID", 5)
{
    Direction = ParameterDirection.Input,
    DbType = DbType.Int32,
    Size = 500
};

var _beginDate = new SqlParameter("BeginDate", "")
{
    Direction = ParameterDirection.Output,
    DbType = DbType.String,
    Size = 500
};

var _endDate = new SqlParameter("EndDate", "")
{
    Direction = ParameterDirection.Output,
    DbType = DbType.String,
    Size = 500
};

这一切看起来都很正常,然后我执行以下操作:

string begin;
string end;
var sql = $"exec [dbo].[GetDateRange] @ID, @BeginDate OUTPUT, @EndDate OUTPUT";

using (var dr = context.Database.ExecuteSqlQuery(sql, ID, _beginDate, _endDate))
{
    while (dr.DbDataReader.Read())
    {
        var thing = dr.DbDataReader[0].ToString();
    }
    dr.DbDataReader.Close();
    begin = _beginDate.Value.ToString();
    end = _endDate.Value.ToString();
}

在使用结束之前,我短暂地获得了第一次约会,但我似乎永远无法获得第二次约会。关闭数据读取器后,我也有空字符串。

如果重要的话,我的存储过程就是这样:

    @ID INT,
    @BeginDate DATE OUTPUT,
    @EndDate DATE OUTPUT
BEGIN
    SET NOCOUNT ON;
    DECLARE @Query1 NVARCHAR(1000)
    DECLARE @Query2 NVARCHAR(1000)

    SELECT @Query1 = BeginDate,
           @Query2 = EndDate 
    FROM DateRange 
    WHERE ID = @ID
    
    DECLARE @ParmDefinition1 NVARCHAR(50) = N'@BeginDateOUT DATE OUTPUT';
    DECLARE @ParmDefinition2 NVARCHAR(50) = N'@EndDateOUT DATE OUTPUT';

    EXEC sp_executesql @Query1, @ParmDefinition1, @BeginDateOUT = @BeginDate OUTPUT
    EXEC sp_executesql @Query2, @ParmDefinition2, @EndDateOUT = @EndDate OUTPUT
END

或者我的存储过程可能是问题所在。我有一个约会,但只能保持很短的时间。 sp_executesql 的问题在于它必须转到 OUTPUT 参数,我不能将结果分配给除 INT 变量之外的任何东西。我需要表中存储代码中的两个日期。

如果有办法做到这一点,并且只返回基本上相当于一个理想的小表结果。

感谢任何可以为我指明正确方向的人。

【问题讨论】:

  • ExecuteSqlQuery 不是 EF Core 方法!?使用 FromSqlRaw
  • @ErikEJ 这仅适用于存在的实体,这不会从我的研究中返回。你检查了引用的代码吗?
  • 查看 EF Core Power Tools 以了解如何做到这一点。
  • @ErikEJ 如果您发布了一个关于如何/如果没有第 3 方库的情况下这是不可能的答案,我可能会或可能不会从我的商店获得使用许可,并且似乎在至少部分由您撰写。

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


【解决方案1】:

因此,至少在 ADO 中,如果您不关闭数据读取器,您将永远无法取回输出参数。 在您的示例中,这应该足以满足您的需求:

    string begin;
    string end;
    var sql = $"exec [dbo].[GetDateRange] @ID, @BeginDate OUTPUT, @EndDate OUTPUT";

    using (var dr = context.Database.ExecuteSqlQuery(sql, ID, _beginDate, _endDate))
    {
        while (dr.DbDataReader.Read())
        {
            var thing = dr.DbDataReader[0].ToString();
        }
        dr.DbDataReader.Close();
        begin = _beginDate.Value.ToString();
        end = _endDate.Value.ToString();
    }

不过,here 中提到了一个有趣的解决方案,它似乎正好解决了您的痛点。

【讨论】:

  • 是的,我知道这一点,但是对于我引用的扩展类,没有选项可以关闭博士。我不认为 dr.Dispose() 会做同样的事情,而 using 无论如何都会这样做......有点令人困惑。该代码看起来很像我正在做的事情,但它使用的是 dbfactories... EF 的交互方式有点奇怪。
  • 文档说,这个方法在里面:docs.microsoft.com/en-us/dotnet/api/…
  • 似乎有两个数据读取器...我正在使用this one
  • 感谢分享,所以在你提到我的文档中,有一个对我提到的属性的引用,它看起来像是内置在你的 DbDataReader 类中:docs.microsoft.com/en-us/dotnet/api/…,所以如果你可以访问它,你可以关闭你的数据阅读器。
  • 好吧,我觉得有点不好意思,因为没有看到那个额外的层,抱歉......我看到了 Close 属性,但我仍然没有得到分配给变量的结果。即使将分配放在 using 中,以防万一这是范围问题。
【解决方案2】:

所以看起来我不需要使用 sp_executesql 也不需要任何 OUT 参数。

所以我将存储过程更改为这个,并对表中保存的基础查询进行了细微更改,以删除其中的选择,从而基本上允许在存储过程中构造 sql。

ALTER PROCEDURE [dbo].[GetDateRange] 
@ID INT

作为 开始 设置无计数; 声明 @Query1 NVARCHAR(1000) 声明@Query2 NVARCHAR(1000) SELECT @Query1 = BeginDate, @Query2 = EndDate FROM DateRange WHERE ID = @ID

DECLARE @Test NVARCHAR(1000) = 'SELECT ' + @Query1 + ' AS BeginDate, ' + @Query2 + ' AS EndDate'
EXECUTE (@Test)

结束

然后我可以使用现有代码执行以下操作:

        var ID = new SqlParameter("ID", 1)
        {
            Direction = ParameterDirection.Input,
            DbType = DbType.Int32,
            Size = 500
        };

        DataTable dates = new DataTable();
        var sql = $"exec [dbo].[GetDateRange] @ID";

        using (var dr = context.Database.ExecuteSqlQuery(sql, ID))
        {
                dates.Load(dr.DbDataReader);
        }

【讨论】:

  • 由于动态质量,不确定如何格式化 SQL 的中间部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-13
  • 2020-12-15
  • 2017-09-23
  • 2020-04-10
  • 1970-01-01
  • 1970-01-01
  • 2016-07-21
相关资源
最近更新 更多