123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Security.Cryptography;
- namespace EasyDevCore.Common
- {
- /// <summary>
- ///
- /// </summary>
- public enum SequentialGuidType
- {
- /// <summary>
- /// The sequential as string (sepecific for MySQL, PostgreSQL ...)
- /// </summary>
- SequentialAsString,
- /// <summary>
- /// The sequential as binary (sepecific for Oracle)
- /// </summary>
- SequentialAsBinary,
- /// <summary>
- /// The sequential at end (sepecific for Microsoft SQL Server)
- /// </summary>
- SequentialAtEnd
- }
- /// <summary>
- ///
- /// </summary>
- public static class SequentialGuidGenerator
- {
- /// <summary>
- /// The _RNG
- /// </summary>
- private static readonly System.Security.Cryptography.RandomNumberGenerator _rng = System.Security.Cryptography.RandomNumberGenerator.Create();
- /// <summary>
- /// Create a sequential GUID.
- /// </summary>
- /// <param name="guidType">Type of the GUID.</param>
- /// <returns></returns>
- public static Guid NewSequentialGuid(SequentialGuidType guidType)
- {
- return NewSequentialGuid(guidType, 1)[0];
- }
- /// <summary>
- /// Nexts the sequential unique identifier.
- /// </summary>
- /// <param name="guid">The unique identifier.</param>
- /// <param name="guidType">Type of the unique identifier.</param>
- /// <returns></returns>
- public static Guid NextSequentialGuid(Guid guid, SequentialGuidType guidType)
- {
- byte[] guidBytes = guid.ToByteArray();
- UInt32 nextID = 0;
- switch (guidType)
- {
- case SequentialGuidType.SequentialAsString:
- case SequentialGuidType.SequentialAsBinary:
- nextID = BitConverter.ToUInt32(guidBytes, 12) + 1;
- Buffer.BlockCopy(BitConverter.GetBytes(nextID), 0, guidBytes, 12, 4);
- break;
- case SequentialGuidType.SequentialAtEnd:
- nextID = BitConverter.ToUInt32(guidBytes, 6) + 1;
- Buffer.BlockCopy(BitConverter.GetBytes(nextID), 0, guidBytes, 6, 4);
- break;
- default:
- throw new NotSupportedException(guidType.ToString());
- }
- return new Guid(guidBytes);
- }
- /// <summary>
- /// Nexts the sequential unique identifier.
- /// </summary>
- /// <param name="guid">The unique identifier.</param>
- /// <returns></returns>
- public static Guid NextSequentialGuid(Guid guid)
- {
- return NextSequentialGuid(guid, SequentialGuidType.SequentialAtEnd);
- }
- /// <summary>
- /// Create a sequential GUID (sepecific for Microsoft SQL Server)
- /// (SequentialGuidType = SequentialGuidType.SequentialAtEnd).
- /// </summary>
- /// <returns></returns>
- public static Guid NewSequentialGuid()
- {
- return NewSequentialGuid(SequentialGuidType.SequentialAtEnd, 1)[0];
- }
- /// <summary>
- /// Create a sery sequential GUIDs (sepecific for Microsoft SQL Server)
- /// (SequentialGuidType = SequentialGuidType.SequentialAtEnd).
- /// </summary>
- /// <param name="count">The count.</param>
- /// <returns></returns>
- public static Guid[] NewSequentialGuid(int count)
- {
- return NewSequentialGuid(SequentialGuidType.SequentialAtEnd, count);
- }
- /// <summary>
- /// Create a sery sequential GUIDs.
- /// </summary>
- /// <param name="guidType">Type of the GUID.</param>
- /// <param name="count">The count.</param>
- /// <returns></returns>
- public static Guid[] NewSequentialGuid(SequentialGuidType guidType, int count)
- {
- byte[] randomBytes = new byte[10];
- _rng.GetBytes(randomBytes);
- UInt32 sequentialID = BitConverter.ToUInt32(randomBytes, 6);
- long timestamp = DateTime.UtcNow.Ticks / 10000L;
- byte[] timestampBytes = null;
- int increment = -1;
- Guid[] listGuids = new Guid[count];
- byte[] guidBytes = new byte[16];
- timestampBytes = BitConverter.GetBytes(timestamp);
- switch (guidType)
- {
- case SequentialGuidType.SequentialAsString:
- case SequentialGuidType.SequentialAsBinary:
- Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 6); //Get first 6 byte
- if (BitConverter.IsLittleEndian)
- {
- Array.Reverse(timestampBytes);
- }
- Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6);
- // If formatting as a string, we have to reverse the order
- // of the Data1 and Data2 blocks on little-endian systems.
- if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian)
- {
- Array.Reverse(guidBytes, 0, 4);
- Array.Reverse(guidBytes, 4, 2);
- }
- while (increment++ < count)
- {
- Buffer.BlockCopy(BitConverter.GetBytes(sequentialID++), 0, guidBytes, 12, 4); //Move last rest 4 byte
- listGuids[increment] = new Guid(guidBytes);
- }
- break;
- case SequentialGuidType.SequentialAtEnd:
- Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 6); //Get first 6 byte
- if (BitConverter.IsLittleEndian)
- {
- Array.Reverse(timestampBytes);
- }
- Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6);
- while (++increment < count)
- {
- Buffer.BlockCopy(BitConverter.GetBytes(sequentialID++), 0, guidBytes, 6, 4); //Move last rest 4 byte
- listGuids[increment] = new Guid(guidBytes);
- }
- break;
- }
- return listGuids;
- }
-
- }
- }
|