1

我有一个针对 SQL Server 2012 运行的 C# OLTP 应用程序。我希望它在其数据库位于 AlwaysOn 可用性组中时发生故障转移时不会中断运行。为了从因故障转移而中断的事务中恢复,我使用另一个类 (RetryableSqlCommand) 包装了 C# SqlCommand 对象,该类捕获与故障转移相关的异常(连接断开、无法强化远程事务等)并自动重试它们在指数退避延迟之后。在小型测试应用程序中,此代码完全按照我的意愿工作。当在完整的 OLTP 应用程序中以中等负载(每秒几百个事务)运行时,我在手动故障转移数据库时遇到错误。

该错误总是发生在插入一个主记录和 4 个详细记录的最常调用的存储过程之一中。存储过程始终将插入的主记录和详细记录的 ID 作为 OUTPUT 参数返回。C# 代码如下所示:

using (RetryableSqlCommand cmd = conn.CreateCommand())
{
  cmd.CommandText = "InsertComplexItem";
  cmd.CommandType = CommandType.StoredProcedure;
  // add sproc input parameters for master and detail records
  await cmd.ExecuteNonQueryAsync();

  // retrieve IDs of inserted records
  var masterId = (long)(cmd.Parameters["MasterId"].Value);   <-- InvalidCastException
  var detail1Id = (long)(cmd.Parameters["Detail1Id"].Value);
  var detail2Id = (long)(cmd.Parameters["Detail2Id"].Value);
  var detail3Id = (long)(cmd.Parameters["Detail3Id"].Value);
  var detail4Id = (long)(cmd.Parameters["Detail4Id"].Value);
}

我在上面提到的那一行得到了一个 InvalidCastException,因为我从调试日志中确定,ID 是作为 DBNulls 从存储过程返回的。据我所知,这永远不会发生,因为存储过程将所有记录插入到单个事务中。如果事务被中断,应该会有一个异常被 RetryableSqlCommand 类捕获并重试。InvalidCastException 的任何解释?

4

0 回答 0