【问题标题】:Unable to map SQL Query Response to C# variables无法将 SQL 查询响应映射到 C# 变量
【发布时间】:2020-09-15 05:34:44
【问题描述】:

我有这个 SQL 查询脚本,我试图通过 ADO.Net 代码调用它。

DECLARE   
  @Error NVARCHAR(MAX)
DECLARE
  @Errors TABLE
  (
    [Column_Name] VARCHAR(MAX),
    [Message] VARCHAR(MAX)
  )

IF NOT EXISTS(...)  
BEGIN  
  INSERT INTO @Errors
  SELECT
    'Col1',
    'value does not exist.'
END

IF NOT EXISTS(...)  
BEGIN  
  INSERT INTO @Errors
  SELECT
    'Col2',
    'value does not exist.'
END

IF EXISTS (SELECT * FROM @Errors)
BEGIN 
  SET @Error = (  
    SELECT  
      [Column_Name],
      [Message]
    FROM
      @Errors
    FOR JSON PATH, INCLUDE_NULL_VALUES
  );

  SELECT @Error AS 'Error_Message'
END
ELSE
BEGIN
    SELECT TOP(1) Id
    FROM dbo.table
END

这是 C# 代码

using (var conn = await _connectionFactory.OpenConnectionAsync(database: "dbName", readOnly: true))
{
    using (var cmd = conn.CreateCommandFromSqlFile(path, "test.sql"))
    {
        string errors = string.Empty;
        Guid id;

        using (DataReader reader = await cmd.ExecuteReaderAsync(ct))
        {
            if (reader.HasRows)
            {
                while (await reader.ReadAsync(ct))
                {
                    errors = reader.GetString("Error_Message");
                    id = reader.GetGuid("Id");
                }
            }
        }
    }
}

SQL 脚本始终根据条件返回Error_MessageId。如果填充了@Errors 表,则返回Error_Message,如果没有错误,则返回Id

我试图在 c# 代码中获取这些值,但它在 while 块中引发异常,因为其中一个值,Error_MessageId 将不存在。

我需要帮助才能将这些值优雅地添加到我的 C# 代码中。有办法吗?

【问题讨论】:

  • 使用输出参数。
  • @DaleK - SQL 脚本不是存储过程或函数,它只是一个普通的 SQL 脚本。
  • 所以?您可以将参数与普通 SQL 一起使用...我一直将它们用于少数返回值,因为您不需要阅读器和/或 DataTables 等,它们的性能更好。

标签: c# sql-server ado.net


【解决方案1】:

我不认为有一种“优雅”的方式可以按照您构建它的方式进行,恕我直言

  • 您可以使用 c# try catch 来捕获不存在错误时发生的异常,但异常处理速度较慢,不应用作正常的控制设备流程
  • 您可以更改您的查询,使它们都返回相同的列名,这样就不再有任何异常,并且 id 表示为一个字符串,并且您可以使用另一列来指导您该字符串是否为GUId 或错误,以便您可以适当地解析或报告它,或者您尝试解析它并查看它是否有效
  • 您可以更改您的查询,使其始终有两列 - 一个字符串和一个 GUId,其中一个始终为 null,并使用 null 来确定您拥有哪种类型的东西
  • 您始终可以同时选择错误和 ID,并利用 sql server 允许您打开多个结果集这一事实

但实际上,我想我会停止尝试将 SQL 错误作为结果集返回,而只是返回 throw them as exceptions,并在 c# 中捕获它们。采用以空白开头的字符串的模式,检查 col1,如果不存在,则将“col1 不存在”附加到字符串,检查 col2 并可能附加“col2 不存在”.. 然后如果字符串不是空白的 扔掉它,否则返回你的结果集。 C# 将遇到带有有用错误消息的异常(如果您想以不同的方式处理它,而不仅仅是向用户报告,您可以提供可变代码)

【讨论】:

    【解决方案2】:

    你可以使用SqlDataReaderGetName函数

    using (SqlDataReader reader = await cmd.ExecuteReaderAsync(ct))
    {
        if (reader.HasRows)
        {
            while (await reader.ReadAsync(ct))
            {
                var colName = reader.GetName(0);
                if (colName.Equals("Error_Message")
                    errors = reader.GetString("Error_Message");
                else 
                    id = reader.GetGuid("Id");
            }
        }
    }
    

    https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqldatareader.getname?view=dotnet-plat-ext-3.1#System_Data_SqlClient_SqlDataReader_GetName_System_Int32_

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-01
      • 1970-01-01
      • 2023-03-18
      • 2017-05-13
      • 2019-09-27
      • 2019-02-12
      • 2018-09-11
      • 1970-01-01
      相关资源
      最近更新 更多