DateTime.Now.Ticks repeating inside a loop

前端 未结 6 1175
小鲜肉
小鲜肉 2021-01-27 02:55

I am trying to generate a unique ID for the primary key of a table and I am using DateTime.Now.Ticks for it. That\'s a requirement for now we can\'t use Ident

6条回答
  •  日久生厌
    2021-01-27 03:29

    Creating a unique sequential Id in C#

    Creating a unique sequential Id based of DateTime.Now.Ticks is challenging. But can be done if you consider the points in @ZunTzu's excellent answer.

    The code below is used by the Kestrel HTTP server. It's used when Kestrel generates request IDs for traces.

    internal static class CorrelationIdGenerator  
    {
        private static readonly string _encode32Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
    
        private static long _lastId = DateTime.UtcNow.Ticks;
    
        public static string GetNextId() => GenerateId(Interlocked.Increment(ref _lastId));
    
        private static unsafe string GenerateId(long id)
        {
            char* charBuffer = stackalloc char[13];
    
            charBuffer[0] = _encode32Chars[(int)(id >> 60) & 31];
            charBuffer[1] = _encode32Chars[(int)(id >> 55) & 31];
            charBuffer[2] = _encode32Chars[(int)(id >> 50) & 31];
            charBuffer[3] = _encode32Chars[(int)(id >> 45) & 31];
            charBuffer[4] = _encode32Chars[(int)(id >> 40) & 31];
            charBuffer[5] = _encode32Chars[(int)(id >> 35) & 31];
            charBuffer[6] = _encode32Chars[(int)(id >> 30) & 31];
            charBuffer[7] = _encode32Chars[(int)(id >> 25) & 31];
            charBuffer[8] = _encode32Chars[(int)(id >> 20) & 31];
            charBuffer[9] = _encode32Chars[(int)(id >> 15) & 31];
            charBuffer[10] = _encode32Chars[(int)(id >> 10) & 31];
            charBuffer[11] = _encode32Chars[(int)(id >> 5) & 31];
            charBuffer[12] = _encode32Chars[(int)id & 31];
    
            return new string(charBuffer, 0, 13);
        }
    }
    

    The key take aways are:

    • Use DateTime.UtcNow.Ticks as a 'seed'.
    • Use Interlocked.Increment to increment
    • In an effort to avoid collisions when called from different machines. You could consider prefixing with the machine name hash (Not perfect but will work for most use cases).

    When trying to do this myself for a IoT project I discovered this code when reading this excellent blog post, aptly named Generating IDs in C# 'safely' and efficiently.

提交回复
热议问题