使用随机类C#生成BIGINT密钥

时间:2014-12-10 10:02:43

标签: c# linq random

我的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

4 个答案:

答案 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类更好的随机生成器(更不可预测)。