使用DateTime.Now作为唯一标识符的主要部分有什么问题?

10

我曾使用RNGCryptoServiceProvider来生成基于字符串的订单ID,但有4个实例其中ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@$%^*()_-会生成已存在的订单ID。

这让我思考...

为什么我们不能像这样使用:

<html>
...
<p>@GenerateOrderId()</p>
...
</html>

和:

public string GenerateOrderId()
{
   return "OID" + 
      DateTime.Now.Year + DateTime.Now.Month +
      DateTime.Now.Day + 
      DateTime.Now.Hour + 
      DateTime.Now.Minute + 
      DateTime.Now.Second + 
      DateTime.Now.Millisecond;
}

有人告诉我这是个不好的想法,但并没有解释或原因,它仍然印象深刻。 ... 我想使用它的原因是因为它将始终是唯一的。


1
你为什么确定它会一直是唯一的? - D'Arcy Rittich
11
为什么不使用 GUID? - Bill
6个回答

19

计算机的工作速度非常快,你很可能立即生成重复的订单ID。

你最好使用GUID(全球唯一标识符)[MSDN-C#][MSDN-SQL] (在SQL世界中称为UNIQUEIDENTIFIER)。


2
此外,DateTime.Now通常不是实时采样的。根据MSDN的说法,“此属性的分辨率取决于系统计时器”。 - drch
Math.floor(Math.random() * 1000)*Date.now(); 这个怎么样? - Squirrl

7

它不会始终是唯一的。

如果在同一毫秒内执行相同的过程,则它将是相同的。

正如 @Bill 所述,您应该使用 GUID 生成唯一字符串。


6

不要多次调用 Now 属性获取当前时间,因为在添加字符串时,当前时间可能会改变。你可以使用 DateTime.Now.ToString("yyyyMMddHHmmssfff") 或类似的方法,但更好的选择是使用 Guid.NewGuid()


具体来说,举个例子,假设你在评估 DateTime.Now.Hour 时是15:59,但当你评估 DateTime.Now.Minute 时时间已经变成了16:00。那么你字符串的相应部分将会显示为 1500,这很令人困惑,因为它与生成订单ID的真实时间相差约一小时。 - Jeppe Stig Nielsen
如果发生这种情况,可能会出现重复,如果已经生成了1500的订单ID。谢谢你提醒我。 - Arrow
1
@EvilCokeMachine 没错。因此,如果您坚持使用 DateTime.Now,请确保只调用一次。您可以将该值保存到本地变量中,并多次读取该变量。 - Jeppe Stig Nielsen
我喜欢使用NewGUID,尽管对于许多需要通过电话引用它的客户来说确实很麻烦。从MSDN上看,似乎无法创建自定义格式的GUID。 - Arrow

4

2

我建议让你的数据库处理这个任务,但如果你必须在代码中完成这个任务,那么请使用 GUID。GUID 重复的概率非常低。

  public string GenerateOrderId()
  {
    return System.Guid.NewGuid().ToString();
  }

0
不是要重复强调,但您对DateTime.Now的使用比您想做的事情更值得关注。您可以重写您的方法并更简洁地实现相同的目标:
public string GenerateOrderID()
{
  return "OID" + DateTime.Now.Ticks.ToString();
}

我仍然建议使用 Guid 而不是这种方法。但是,99% 的情况下,每次调用 Ticks 属性都会给出一个不同的数字。


1
系统计时器的分辨率仍然太低,无法将其用作唯一值。MSDN指出,≥ NT 3.5的大约分辨率为~10ms(对于计算机来说是一个漫长的时间)。另一方面,GUID正是为解决这个问题而设计的。 - ollb
@ollb 我同意,这就是为什么我建议使用 Guid 而不是这种方法。我的回答只是建议,如果你一定要使用 DateTime.Now,那么你应该只调用它一次。 - sellmeadog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接