我最近用一个简单的解决方案解决了一个难以捉摸的错误。希望这对某人有帮助。我的环境:
症状相当奇怪。当导航到某些页面时,我会收到以下错误:
SqlException: New request is not allowed to start because it should come with valid transaction descriptor.
第一次看到此错误后,所有其他页面现在都会收到错误,但不是相同的错误。它会在以下两个错误之间交替出现:
IndexOutOfRangeException: username2_13_0
at Microsoft.Data.SqlClient.SqlDataReader.GetOrdinal(string name)
和
IndexOutOfRangeException: id1_14_
at Microsoft.Data.SqlClient.SqlDataReader.GetOrdinal(string name)
(上述错误的奇怪之处在于这些列确实存在于正在执行的查询中)
另一个有趣的异常是该错误仅持续存在于同一数据库的连接字符串上。这是一个多租户应用程序,每个租户使用不同的数据库。只有您最初触发
SqlException: New request is not allowed to start because it should come with valid transaction descriptor.
的租户才会收到持久 IndexOutOfRangeException
。这让我认为连接池与错误有关。
在 StackOverflow 和网络上搜索解决方案表明它与分布式事务(尽管我们不使用分布式事务)或无效架构有关。
事实证明,该问题与 SQL Server 的 Always Encrypted 列级加密有关。
我使用 Azure 作为我的密钥存储并使用
SqlColumnEncryptionAzureKeyVaultProvider
,如下所示:
var credential = new Azure.Identity.ClientSecretCredential(m3Config.AzureTenantId, m3Config.AzureClientId, m3Config.AzureClientSecret);
SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(credential);
SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customProviders: new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>(capacity: 1, comparer: StringComparer.OrdinalIgnoreCase)
{
{
SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, akvProvider
}
});
SqlConnection.ColumnEncryptionKeyCacheTtl = TimeSpan.FromDays(1);
通过反复试验,我发现我的 Azure 客户端密钥已过期。该问题已通过使用未过期的客户端密钥得到解决。
感谢微软提供了这个非常令人困惑的转移注意力的错误消息!