【问题标题】:Why does Azure SQL database returns malformed results sometimes?为什么 Azure SQL 数据库有时会返回格式错误的结果?
【发布时间】:2022-01-20 16:15:04
【问题描述】:

我有一个后端 Web API(AppService、.Net Core 3.0)访问的 Azure SQL 数据库, 两者都托管在同一个 Azure 区域中。

后端使用Dapper 查询/映射数据库中的数据。 只是正常的电话,例如:

connection.Query<...>
connection.QueryMultiple(...)

一切都很完美......但有时,会发生一些事情...... 通常当数据库处于高负载时,有时处于中等负载时..

查询开始随机失败并出现不同的错误:

System.InvalidOperationException: No columns were selected

System.ArgumentException: When using the multi-mapping APIs ensure you set the splitOn param
if you have keys other than Id (Parameter 'splitOn')

System.ApplicationException: Attempting to cast a DBNull to a non nullable type!
Note that out/return parameters will not have updated values until the data stream completes
(after the 'foreach' for Query(..., buffered: false), or after the GridReader has been
disposed for QueryMultiple)

最糟糕的是,有时根本没有错误,只返回空结果集 甚至是一些列值缺失的格式错误的结果。

我花了很多时间寻找原因,但没有运气。 问题主要是查询中的一些错误,这里不是这种情况。

我执行相同的简单查询 20 次,成功 15-16 次,错误 4-5 次。

一段时间后,一切恢复正常,一切正常。

我感觉 SQL 数据库出于某种原因正在返回损坏的数据, 但我不知道如何调查/追踪它???

我没有想法 - 非常欢迎任何提示检查/寻找什么

更新:

我可以看到这是 Dapper 引发前两个异常的代码:

private static Exception MultiMapException(IDataRecord reader)
{
    bool hasFields = false;
    try { hasFields = reader != null && reader.FieldCount != 0; }
    catch { /* don't throw when trying to throw */ }
    if (hasFields)
        return new ArgumentException("When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id", "splitOn");
    else
        return new InvalidOperationException("No columns were selected");
}

所以可能会有更有意义的异常被空的catch 块吞噬。不知道有没有办法让我以某种方式看到那个?

这是@Charlieface 要求的示例:

CREATE PROCEDURE [dbo].[spDossierPhoto_Get]
(
    @LanguageID nvarchar(20),
    @PhotoID uniqueidentifier
)   
AS  

    SELECT 
        photo.*
    FROM
        viewDossierPhoto AS photo
    WHERE 
        (photo.DossierPhoto_LanguageID = @LanguageID) AND
        (photo.DossierPhoto_PhotoID = @PhotoID)
    
RETURN

我再重复一遍 - 它与错误的语法、未执行的案例或任何愚蠢的错误没有任何关系......确切的代码,准确的一切,数百个这样的查询,未触及......正在运行一年多了,调用了数百万次都没有问题 - 最近开始失败并出现异常。

相同的参数,相同的查询,相同的一切......大部分时间都能完美运行,然后由于某种原因开始失败

【问题讨论】:

  • 执行查询的单个 API 请求在单个线程中执行。甚至不使用asyncawait,它们可能会在不同的线程上恢复。当然,有许多请求是并行执行的,就像任何其他 ASP.Net 应用程序一样。
  • 嗯,我明白你的意思了,查询似乎没有问题。虽然不知道为什么你会在上面使用QueryMultiple。您使用的是最新版本的 Dapper 吗?也许你可以设置一个断点(或捕获第一次机会异常)并观察在这种情况下实际数据正在经历什么
  • @Charlieface,谢谢,示例一通过Query 执行,其他一些返回多个结果集的SP 通过QueryMultiple 调用。但无论如何 - 再次重复 - 所有这些工作都很好,直到开始发生一些事情并且......过了一会儿,恢复正常。有没有办法可以调试 Azure AppService(或至少记录一些东西)???因为,在开发环境中,问题是不可重现的......
  • 可能相关:如果有人更改了视图,您需要使用sp_refreshview 重新编译它。因此,如果您有某种自动化系统可以删除和重新创建列或类似的,那可能就是问题

标签: sql-server azure asp.net-core


【解决方案1】:

System.InvalidOperationException:未选择任何列

如果 SP 返回可变结果集,那么这个问题确实很麻烦,尤其是在 QueryMultiple 情况下。
请求:像“HasResult”这样的属性来检查它是否有结果将有助于避免出现“阅读器已被处理;....”错误。

System.ArgumentException:使用多映射 API 时,如果您的键不是 Id,请确保设置 splitOn 参数 >(Parameter 'splitOn')

  • 您需要在选择查询中包含要拆分的列。您选择了 * - 所以Dapper 找不到匹配的列来拆分对象。

  • 而不是 * 写列名。

  • splitOn参数需要指定为分割点,默认为Id。如果有多个分割点,您需要将它们添加到逗号分隔的列表中。

  • Id 参数行为(IN/OUT/INOUT)应该在两个地方同步,即在存储过程和 C# 中。

请参考githubSO Thread,DBNullthis了解更多详情。

【讨论】:

    猜你喜欢
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-22
    相关资源
    最近更新 更多