c# - 使用 SqlCommand.ExecuteScalar() 从序列中选择在高磁盘使用率时返回 NULL

标签 c# sql-server ado.net sql-server-2014 alwayson

我遇到 SqlCommand.ExecuteScalar() 有时在生产环境中返回 NULL

我在这里遇到了很多类似的问题,最接近的是:SqlCommand.ExecuteScalar returns null but raw SQL does not .但给出的建议与我的情况无关。

代码示例在这里:

using (var connection = new SqlConnection(connectionString))
{
    connection.Open();
    using (var command = connection.CreateCommand())
    {
        command.CommandText = "SELECT NEXT VALUE FOR Seq_Revision";
        command.CommandType = CommandType.Text;

        return (long)command.ExecuteScalar(); //<---ExecuteScalar() here returns NULL sometimes
    }
}

Seq_Revision 这是简单的 MSSQL 序列,如下所示:

CREATE SEQUENCE [dbo].[Seq_Revision] 
 AS [bigint]
 START WITH 0
 INCREMENT BY 1
 MINVALUE -9223372036854775808
 MAXVALUE 9223372036854775807
 CACHE  10 
GO

而且我很确定它实际上永远不会返回 NULL。


此外,当此代码示例中返回 NULL 时,我也观察到类似的奇怪(不可重复的行为),同时我确定具有此 ID 的实体:

NHibernate.ISession.Get<FooEntity>(entityId)

有趣的是,当 SQL 节点上存在高磁盘事件时(磁盘队列 长度 > ~50),通过此方法返回 NULL 与时间范围密切相关.

这可能很重要:我们使用具有 2 个节点的 AlwaysON 集群,其中一个节点以读取模式使用(连接字符串中的 ApplicationIntent=READONLY)。

MSSQL 版本是:

Microsoft SQL Server 2014 (SP2-CU5) (KB4013098) - 12.0.5546.0 (X64) 
    Apr  3 2017 14:55:37 
    Copyright (c) Microsoft Corporation
    Enterprise Edition: Core-based Licensing (64-bit) on Windows NT 6.3 <X64> (Build 9600: )

最佳答案

我认为问题可能与序列缓存有关。

也许有一些未处理的东西导致缓存中剩余的序列号丢失。

尝试在你的序列中禁用缓存:

ALTER SEQUENCE [dbo].[Seq_Revision] 
 NO CACHE
GO

或者尝试使用更高的缓存值:

ALTER SEQUENCE [dbo].[Seq_Revision] 
 CACHE 100
GO

关于c# - 使用 SqlCommand.ExecuteScalar() 从序列中选择在高磁盘使用率时返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49325105/

相关文章:

c# - 如何从 C# 获取 COM 组件的 ProgID?

c# - 如何在不使用 EF 的情况下连接到 ASP.NET Core Web API 中的数据库?

sql-server - SQL Server Management Studio 2008 没有脚本表权限

c# - 存储库模式,共享连接

c# - 合并两个数据表

c# - 我的选择命令不起作用

c# - 没有配置文件的 WCF/服务引用

C#:设计一个更快的断言函数,仅在触发时格式化错误字符串

sql-server - 如何查看旧的 Sybase sql (.db) 数据库数据并转换为 Sql Server

mysql - 查找SQL表中的特定数据