ExecuteScalar方法返回值 及 DBnull和NUll的区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ExecuteScalar方法返回值 及 DBnull和NUll的区别相关的知识,希望对你有一定的参考价值。
参考技术A cmd.ExecuteScalar()方法返回值类型为object当查询没有任何返回值时会返回Null,表现为直接在SQL Management Studio内查询,没有返回值,为空白。则ExecuteScalar()返回NULL值
当查询有返回值,如果第一行第一列值为NULL,表现为直接在SQL Management Studio内查询,显示为NULL,则ExecuteScalar()返回DBNull值
DBNull.ToString()为空字符串,NULL.ToString()会报异常。所以最好先对返回值 进行判断是否为空再作处理。
DBNull 和 NULL的区别
null是C#中的关键字,表示此引用不指向任何地址。
DBNull只是一个普通的类,继承自object,没添加任何方法属性,其有一个唯一的实例Value。它的存在仅仅只是为了表示从数据库读取数据时遇到的数据库中的null值。
可以用Convert.IsDBNull()方法判断是不是DBNull本回答被提问者和网友采纳
当磁盘使用率高时,使用 SqlCommand.ExecuteScalar() 从序列中选择返回 NULL
【中文标题】当磁盘使用率高时,使用 SqlCommand.ExecuteScalar() 从序列中选择返回 NULL【英文标题】:Select from sequence with SqlCommand.ExecuteScalar() returns NULL when high disk usage 【发布时间】:2018-03-16 16:07:01 【问题描述】:我在生产环境中遇到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)
有趣的是,通过这种方法返回 NULL
与 SQL 节点上存在大量磁盘活动(磁盘队列长度 > ~50)的时间范围非常相关。
这可能很重要:我们使用带 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: )
【问题讨论】:
ExecuteScalar
返回null
表示:没有返回行。如果返回的行为空值,则为DBNull.Value
。这没有回答“为什么?”,但它可能是有用的上下文
@MarcGravell,我知道。但是你相信 SELECT NEXT VALUE FOR Seq_Revision 返回 0 行吗?听起来不可能。
我不知道;这是个好问题
NEXT VALUE FOR
不支持只读数据库。请参阅docs.microsoft.com/en-us/sql/t-sql/functions/… 的限制和限制 => 从连接字符串中删除 ApplicationIntent=READONLY
您能否测试这种情况,例如if (command.GetType() == typeof(DBNull))
或者它用InvalidCastException
捕获它,然后检查值或在Thread.Sleep(1000);
之后重试,以排除磁盘的计时问题.也是添加一些日志记录以帮助形成minimal reproducible example 的好地方,我猜它是间歇性的,并且只能在 IO 压力下重现。
【参考方案1】:
我认为问题可能与序列缓存有关。
也许有一些未处理的东西导致缓存中剩余的序列号丢失。
尝试禁用序列中的缓存:
ALTER SEQUENCE [dbo].[Seq_Revision]
NO CACHE
GO
或尝试使用更高的缓存值:
ALTER SEQUENCE [dbo].[Seq_Revision]
CACHE 100
GO
【讨论】:
谢谢,我们会试试这个理论。但这无法解释为什么我有时会从 ISession.Get(id) 获得 NULL,而我确信具有此 ID 的实体确实存在:NHibernate.ISession.Get以上是关于ExecuteScalar方法返回值 及 DBnull和NUll的区别的主要内容,如果未能解决你的问题,请参考以下文章
为啥 OleDb ExecuteScalar 方法在查询 COUNT 时返回 Decimal?
ExecuteNonQuery,ExecuteReader,ExecuteScalar 区别