如何在C#中生成随机唯一数字

时间:2010-06-17 19:20:15

标签: c# .net sql-server

public int GenPurchaseOrderNum()
{
    Random random = new Random();
    _uniqueNum = random.Next(13287, 21439);
    return UniqueNum;
}

我从数据库中的PONumber列中删除了唯一约束,因为员工 应该只生成P.O. #交易设定时。否则,P.O。 #会有0。

P.O。用于具有唯一约束的数字,这迫使员工生成P.O.在所有情况下,db都不会抛出唯一约束错误。

由于我删除了唯一约束,因此任何引用都没有P.O.将携带0值。否则,为P.O.生成唯一值。 #。但是,我没有db中的唯一约束,这使我很难知道应用程序是否生成了P.O. #是独一无二的。

我该怎么办?

我希望我的问题很清楚

11 个答案:

答案 0 :(得分:11)

GUID在开销方面有点高。具体来说,听起来你需要一个人类可读的PO#号码,这使得GUID不切实际。我更倾向于使用以下场景。

  1. 删除您在该字段上的所有NOT NULL约束。
  2. 使用存储过程创建新PO,使PO#字段为NULL。 Null在所描述的情况下是最合适的,因为在DB NULL的世界中意味着“未知”并且因为你实际上没有PO#,所以它是未知的。
  3. 使用在交易完成时更新字段的存储过程,以递增到下一个可用的采购订单编号。这将发生在服务器端,因此更新来自哪个客户端并不重要,它仍然是该表的唯一。然后,此存储过程可以将更新的结果集(如果需要)返回给客户端,以便他们可以看到新的PO#。
  4. 这是20公尺的视野。

答案 1 :(得分:11)

每次执行新的Random()时都会初始化。这意味着在紧密循环中,您可以多次获得相同的值。您应该保留一个Random实例并继续在同一个实例上使用Next。

//Function to get random number
private static readonly Random getrandom = new Random();
private static readonly object syncLock = new object();
public static int GetRandomNumber(int min, int max)
{
    lock(syncLock) { // synchronize
        return getrandom .Next(min, max);
    }
}

答案 2 :(得分:5)

如果您确实需要随机值,而不是返回int,则可以使用GUID。这些保证是独一无二的:

  

GUID是一个128位整数(16字节),可以在需要唯一标识符的所有计算机和网络中使用。这样的标识符被复制的可能性非常低。

Source

另一种方法是记录最后使用的数字,并在每次需要新PO时简单地增加它。确保你锁定它,这样两个进程就不会尝试同时增加它。

答案 3 :(得分:5)

  • 不要将0用于未知值。添加唯一约束并使用NULL表示未知/未生成的值。如果您愿意,向用户显示NULL为0,但这与问题正交。
  • 不要使用随机生成唯一编号,然后尝试插入,您将不必要地重复逻辑重试和重新生成。使用序列生成器,如UPDATE seqnces SET sequence = sequence+1 OUTPUT INSERTED.sequence WHERE key = 'somekey'
  • 请勿使用随机数生成商品含义值,例如采购订单编号。使用序列生成器,如上所述。

<强>更新

使用SQL Server 2008及更高版本,您可以使用唯一的filtered index作为不等于0的所有内容的约束:

create unique index idxTbaleUniquePoNumber 
 on <table> (po_number) 
 where (po_number > 0);

有点喜欢吃蛋糕,也喜欢吃蛋糕......

答案 4 :(得分:2)

如果你真的想要一系列范围内的一系列唯一随机数(比如13287到21439),我会创建一个包含所有有效整数的列表,然后随机交换它们。如果你愿意,那就是一种解脱。这将为您提供随机,唯一数字的列表。

诀窍是保存该列表,因为如果你真的想要随机,那么生成需要一些时间。然后我会把它放在一个表中,这样你就可以从你需要的地方索引它。

答案 5 :(得分:0)

从你所写的内容来看,你似乎走错了方向:你把随机性与独特性混为一谈。

您已删除特定于域的约束,因此它将符合您编写的代码。如果PONumber的值除了唯一之外没有其他相关性,请让数据库为您生成它,或生成GUID(如果数据库不能),这可以保证生成的值是唯一的。

否则,完全取决于你的努力工作。 您必须生成一个独特的值,记住所有线程和事务问题。

答案 6 :(得分:0)

与之前的海报一样,我建议在随机值上使用唯一值。 Remus建议的序列发生器可能是最好的方法。

但是,如果你真的确实需要随机值,我建议在Random类上使用RNGCryptoServiceProvider,因为它更随机。查看more information的MSDN。还有一个很好的StackOverflow question on RNGCryptoServiceProvider

答案 7 :(得分:0)

我认为你已经走错了道路并开始变得更糟。您所声明的问题没有真正的商业理由或要求,因此很难看出我们的答案如何能够满足您的最终目标。

我认为你应该退后一步,明确制定你的目标,而不考虑实际的实施。

通常,订单系统确实需要唯一的PO,因此您需要对其进行唯一约束。通常,系统不以相同的方式存储PO和“预PO”。 “预PO”通常称为引号或类似的东西,它们通常有自己的编号系统。因此,在具有NULL或0个PO号码时通常不存在冲突,因为没有任何不是真实PO存储的真实PO。即使在想要将它们存储在一起的系统中,它们也只是按照相同的顺序给它们一个数字。

此外,生成采购订单编号的身份完全正确。

答案 8 :(得分:0)

伪随机数怎么样?当然,几乎语言库中随机数的每一个实现都是伪随机数,但是你可以实现的算法会在保持唯一性的同时呈现随机性。

有些人请参阅list of pseudorandom number generators。我喜欢linear feedback shift register的想法,即生成非顺序的数字并且具有定义的句点(即重复数字之间的调用次数)。

答案 9 :(得分:0)

在这样的情况下,由于记录所代表的实体的状态,有一个字段或一组字段根本没有值,我有时想把表分成两个单独的表,是一对一的关系。

假设您的原始表名为PurchaseOrder,其结构如下所示:

table PurchaseOrder
(
    PurchaseOrderID int identity not null,
    -- some other fields that are core to a purchase order
    -- ...
    PONumber int not null,
    -- some other fields that are related to a purchase order when the deal is set
    -- ...

    -- define primary key on PuchaseOrderID
    -- define unique constraint on PONumber field
)

我的建议是将该表拆开,使它看起来像这样:

table PurchaseOrder
(
    PurchaseOrderID int identity not null,
    -- some other fields that are core to a purchase order
    -- ...

    -- define primary key on PuchaseOrderID
)


table PurchaseOrderDealInfo
(
    PurchaseOrderID int not null,
    PONumber int identity not null,
    -- some other fields that are related to a purchase order when the deal is set
    -- ...

    -- define primary key on PurchaseOrderID
    -- define foreign key on PurchaseOrderID related to PurcahseOrder.PurchaseOrderID
    -- define unique constraint on PONumber field
)

现在,您的特定交易信息位于单独的表格中。任何尚未设置交易的采购订单都不会在PurchaseOrderDealInfo表中具有相应的记录。是的,如果要检索与特定采购订单相关的所有信息,则需要将表连接在一起。但是,你会得到一些好处:

  1. 您仍然可以将唯一约束应用于PONumber列。

  2. 您可以利用SQL Server的身份功能为您生成PONumber

  3. 如果您的表中有任何其他特定于交易的列,您只能因为在设置交易之前它们没有值而可以为空,那么一旦将这些列移动到PurchaseOrderDealInfo表中,您就可以设置不允许空值(如果适用)。

  4. 如果您只想检索具有交易的采购订单,则只需查询PurcahseOrderDealInfo表,而无需指定任何过滤条件。当然,如果您还需要来自PurchaseOrder表的信息,那么您将需要进行内部联接。

答案 10 :(得分:0)

数据库中的自动编号PK可以用作唯一的采购订单编号...只需在它成为“真正的”非零采购订单编号时进行读取和复制。

这不是“随机”,但它将是独一无二的。

现在为书呆子回答: 你的计算机不可能在没有混乱的“随机”种子的情况下生成随机数