我的SQLDB中有一个主键为BIGINT(64位) 既然C#没有直接生成64位密钥的机制,我使用以下代码生成密钥。我的问题是我在关键列中看到了随机但聚集的值。
tl.ID = (this.r.Next() << 32) | this.r.Next();
其中tl.ID是LINQ to SQL类并且是LONG。 this.r是随机的实例
Random r = new Random((int)DateTime.Now.Ticks);
DB中的一些值:
MAX:2147483647
Top few values:
2147478265
2147478479
2147478526
2147479034
2147479663
2147480695
2147480783
2147480887
2147480984
2147481817
2147482099
2147482607
2147483321
2147483391
2147483558
2147483644
2147483647
答案 0 :(得分:2)
首先,主键应该是唯一的。
在您的数据库/自动增量中添加一个标识列,您就可以了。
如果需要,添加带有自动增量的新标识列,删除旧标识列,将新标识列重命名为旧名称,您将没事
答案 1 :(得分:1)
你必须在移位之前将数字转换为很长时间,否则这只会移出有效位。
tl.ID = ((long)this.r.Next() << 32) | this.r.Next();
请记住,这个方法并不完美,正如评论中提到的问题所指出的那样,因为Random.Next()
只返回正值,所以实际上只有62个随机位。
答案 2 :(得分:1)
如AlexDev所述,问题出在第一种情况,在将其移位32位之前,应将其转换为长整数。
答案 3 :(得分:1)
问题1 : 使用随机数生成主键可能是一个坏主意,因为最终你最终会发生冲突,因此使用代码时,除非在使用之前检查每个生成的键是否唯一,否则会遇到问题。 如果你真的需要随机数字作为键使用下面的溶剂。
问题2 : Random类方法Next生成一个int,在你的情况下为32位,这将包围,你将只有一半的范围。另一个问题是标准的Random类不是一个好的随机生成器。
问题3 : 使用Random生成的两个Int32并移一个(加入一个long)并附加另一个不是生成64位随机数的最佳方法,你的双倍上升机会(这是一个超出此讨论的加密主题所以我会留在那个:))
<强>解决方案强>: 要真正生成随机Int64,您可以使用Random或甚至更好的RandomNumberGenerator为您的64位数字填充8个字节的数组,并将该数组转换为long(Int64),例如:
using System.Security.Cryptography;
var rng = RandomNumberGenerator.Create();
//bytes to hold number
var bytes = new byte[8];
//randomize
rng.GetNonZeroBytes(bytes);
//Convert
long random = BitConverter.ToInt64(bytes, 0);
这将生成一个真正的64位随机数,RandomNumberGenerator是一个比Random类更好的随机生成器(更不可预测)。