10

I used to use RNGCryptoServiceProvider to generate string-based Order ID's, but, there were 4 instances where ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@$%^*()_- would generate an already-existing Order ID.

And it got me thinking...

Why can't we just use something like:

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

and:

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;
}

I've been told that it's a bad idea, but without any explanation, or reason, it's still stuck in my head. ... The reason I'd like to use this, is because it will always be unique.

John Kraft
  • 6,811
  • 4
  • 37
  • 53
Arrow
  • 2,784
  • 8
  • 38
  • 61

6 Answers6

19

Computers work at nanosecond speeds. You would be guaranteed to generate a duplicate order ID almost immediately.

Your best bet would be to use a GUID [MSDN-C#] [MSDN-SQL] (a.k.a. UNIQUEIDENTIFIER in the SQL world).

FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91
  • 2
    Additionally, DateTime.Now is generally not sampled at real-time. From MSDN, _"The resolution of this property depends on the system timer."_ – drch Aug 07 '12 at 15:40
  • How about `Math.floor(Math.random() * 1000)*Date.now();`? – Squirrl Feb 28 '14 at 06:41
7

It won't always be unique.

If the same process is carried out during the same millisecond, then it will be identical.

As @Bill has stated, you should use a GUID for a unique string.

Community
  • 1
  • 1
Curtis
  • 101,612
  • 66
  • 270
  • 352
6

Never call the Now getter that many times. "Now" may change while you're adding the strings. You could say DateTime.Now.ToString("yyyyMMddHHmmssfff") or similar, but it's much better to use Guid.NewGuid() for this.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • To elaborate, as an example, suppose it's 15:59 when you evaluate `DateTime.Now.Hour`, but when you evaluate `DateTime.Now.Minute` time has changed to 16:00. Then the corresponding part of your string will read `1500` which is confusing as it's approximately one hour off the true time your order ID was generated. – Jeppe Stig Nielsen Aug 07 '12 at 15:41
  • And if that happens, it could possible be a dupe, if there was already an order id generated at 1500.. Thanks for reminding me. – Arrow Aug 07 '12 at 16:42
  • 1
    @EvilCokeMachine Exactly. Therefore, if you insist to use `DateTime.Now`, make sure you call it only once. You may save the value to a local variable and read that variable several times. – Jeppe Stig Nielsen Aug 07 '12 at 16:47
  • I like using NewGUID, though it really is a pain for many customers who have to reference it over the phone. And from the looks of it, on MSDN, you can't actually create a custom-formatted GUID – Arrow Aug 07 '12 at 16:53
4

If you just want a globally unique identifier and aren't bothered about the format, why don't you just use a GUID?

http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx

using System;

class Sample 
{
    public static void Main() 
    {
        Guid g = Guid.NewGuid();
        Console.WriteLine(g);
    }
}

It even has a type in T-SQL (which you may well be using given that you're using ASP.NET)

tomfanning
  • 9,552
  • 4
  • 50
  • 78
2

I recommend letting your database handle that responsibility, but if you must do it in code, then use GUID. GUID has a low probability of being duplicated.

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

Not to beat a dead horse, but your usage of DateTime.Now is of more concern than what you're trying to do. You can rewrite your method and achieve the same goal much more succinctly:

public string GenerateOrderID()
{
  return "OID" + DateTime.Now.Ticks.ToString();
}

I would still recommend using a Guid over this approach. However, 99% of the time, the Ticks property is going to give you a different number each time it's called.

sellmeadog
  • 7,437
  • 1
  • 31
  • 45
  • 1
    The system timers resolution is still too low, to use it as a unique value. MSDN states an approximate resolution of ~10ms for ≥ NT 3.5 (which is an eternity for a computer). The GUID on the other hand is designed for exactly the problem at hand. – ollb Aug 07 '12 at 16:41
  • @ollb I agree which is why I stated that I recommend `Guid` over this approach. My answer simply suggests that if you're set on using `DateTime.Now` then you should only call it once. – sellmeadog Aug 07 '12 at 17:15