为什么IsDBNull为C#中的行版本列返回false,而不管其值如何?
考虑下面的table表.
CREATE TABLE [Entity] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[RowVersion] ROWVERSION NOT NULL
)
INSERT INTO [Entity] ([Id]) VALUES (N'E2A87489-CEB7-4460-BC30-00264538E644')执行下面的T查询时。请注意,查询有意加入一个不存在的记录,这意味着JoinedEntity.RowVersion应该为NULL。但是,与预期的空值不同,我得到了以下结果:一行包含一个包含值0x的列。
SELECT [JoinedEntity].[RowVersion] FROM [Entity] LEFT JOIN [Entity] AS [JoinedEntity] ON [JoinedEntity].[Id] = N'00000000-0000-0000-0000-000000000000'在执行下面的C#代码时,RowVersion列被标记为非空值,执行reader.IsDBNull(0)就可以看出这一点。
var connectionString = "Server=(LocalDb)\\MSSQLLocalDB;Database=master;Integrated Security=True;";
using (var sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
using(var sqlCommand = new SqlCommand("SELECT [JoinedEntity].[RowVersion] FROM [Entity] LEFT JOIN [Entity] AS [JoinedEntity] ON [JoinedEntity].[Id] = N'00000000-0000-0000-0000-000000000000'", sqlConnection))
{
using(var reader = sqlCommand.ExecuteReader())
{
while (reader.Read())
{
var isNull = reader.IsDBNull(0);
Console.WriteLine(isNull);
}
}
}
}在执行下面的the时,可以清楚地看到第一列的“值”为0x,这个0x当然是所有字节数组的起始部分。正如第二列所看到的,应用ISNULL清楚地表明that将该列视为空值。
SELECT [JoinedEntity].[RowVersion], ISNULL([JoinedEntity].[RowVersion], 0x12345) FROM [Entity] LEFT JOIN [Entity] AS [JoinedEntity] ON [JoinedEntity].[Id] = N'00000000-0000-0000-0000-000000000000'然而,IsDBNull in C#返回false。它返回false的原因可能与调用reader.GetValue(0)返回空字节数组(而不是null )的原因相同。这种不一致性意味着在执行附加处理之前不能完全依赖于检查IsDBNull。对于ROWVERSION列,还必须检查长度。在我看来,这似乎是C#团队、team团队的疏忽,或者两者兼而有之。
注意,其他字节数组列类型(如var二进制(Max))不受此影响,并返回预期的空值。
发布于 2021-03-31 11:23:56
在https://github.com/dotnet/SqlClient/issues/255中,这是System.Data.SqlClient和Microsoft.Data.SqlClient中的一个bug。
System.Data.SqlClient代码将不会被修复。将在Microsoft.Data.SqlClient中引入一个突破性的更改,这将使行版本列的IsDbNull()返回正确。将添加一个名为AppContext的LegacyRowVersionNullBehaviour开关,允许使用旧的行为。
https://stackoverflow.com/questions/62410830
复制相似问题