【发布时间】:2011-10-10 13:01:05
【问题描述】:
我的学生表中有两条记录,其中包含行版本字段。我在我的 C# 代码中将该记录的对象创建为学生类。
我的问题是:
- rowversion 数据转换在哪种 C# 兼容数据类型中?
- 如何比较两条记录的 rowversion 并找出 C# 中最新的一条?
【问题讨论】:
我的学生表中有两条记录,其中包含行版本字段。我在我的 C# 代码中将该记录的对象创建为学生类。
我的问题是:
【问题讨论】:
查找最新行版本的一种方法是使用StructuralComparer
var r1 = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00};
var r2 = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF};
bool r1_is_newer = StructuralComparisons.StructuralComparer.Compare(r1, r2) > 0;
结构比较的一个好处是它们会自动处理NULLs
关于BitConverter 的使用。如果使用 BitConverter 将上述字节数组转换为 UInt64 ,那么您最终会得到非常高的数字并且比较毫无意义(因为 rowversion 改变了 1,uint64 转换后的数字改变了大约 2^56)
如果您想在其上添加一些 LINQ 以使其更加缓慢,您可以使用
bool r1_is_newer =
Enumerable.Zip(r1, r2, (b1, b2) => new { b1, b2 })
.SkipWhile(item => item.b1 == item.b2)
.Take(1).Any(item => item.b1 > item.b2);
【讨论】:
> 0 在这种情况下做了什么?
Compare 函数返回一个有符号整数,表示 r1 和 r2 的相对值: - 如果小于 0,则 r1 小于 r2。 - 如果为 0,则 r1 等于 r2。 - 如果大于0,则r1大于r2 ...表示r1较新
rowversion 是 binary(8),如果您使用 SqlCommand/SqlDataReader,将返回为 byte[]。如果你使用 EF 4.1,对应的属性也会是byte[]。
您可以使用BitConverter 转换为UInt64,然后进行比较。您还可以从 SQL Server 返回 rowversion 强制转换为 bigint,这在 C# 中将显示为 long。无论哪种情况,较大的值都会在以后创建。
在我自己的测试中,我发现 rowversion 从一个小的正值开始(不是 0)。如果您确实转换为bigint,则必须考虑当它到达2^64 时会发生什么。就我而言,这不是我必须担心的事情。如果您认为这会在您的数据库中发生,那么您必须在比较中添加逻辑来处理它,或者坚持使用BitConverter.ToUInt64。
另外,如果您的rowversion 列接受NULL,请小心;如果确实如此,您将不得不考虑这一点。
【讨论】:
BitConverter 是个坏主意,因为字节序很小。如果你只比较平等就可以了。但是,当检查哪个是最新的时,您将不会得到正确的结果