我有一个针对SQL Server 2012运行的C#OLTP应用程序。我希望它在数据库位于AlwaysOn可用性组时在故障转移的情况下不间断地运行。为了从因故障转移而中断的事务中恢复,我将C#SqlCommand对象与另一个类(RetryableSqlCommand)包装在一起,该类捕获与故障转移相关的异常(连接丢失,无法强化远程事务等)并自动重试它们在指数退避延迟之后。在小型测试应用程序中,此代码完全按照我的意愿运行。在完整的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的任何解释?