/// <summary> /// 生产唯一识别号 /// </summary> /// <param name="guidType"></param> /// <returns></returns> public static string Next(SequentialGuidType guidType = SequentialGuidType.SequentialAsString) { byte[] randomBytes = new byte[10]; _rng.GetBytes(randomBytes); long timestamp = DateTime.UtcNow.Ticks / 10000L; byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes).ToString("N")); }
private static Guid New(SequentialGuidType guidType) { var randomBytes = new byte[10]; Rng.GetBytes(randomBytes); var timestamp = DateTime.UtcNow.Ticks / 10000L; var timestampBytes = BitConverter.GetBytes(timestamp); if(BitConverter.IsLittleEndian) Array.Reverse(timestampBytes); var guidBytes = new byte[16]; switch(guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // 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); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return new Guid(guidBytes); }
/// <summary> /// /// </summary> /// <param name="guidType"></param> /// <returns></returns> public static Guid NewGuid(SequentialGuidType guidType) { byte[] randomBytes = new byte[10]; _rng.GetBytes(randomBytes); long timestamp = DateTime.Now.Ticks / 10000L; byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.String: case SequentialGuidType.Binary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); if (guidType == SequentialGuidType.String && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.AtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return new Guid(guidBytes); }
/// <summary> /// Base implementation of IPocoPersistor using Entity Framework 6 /// </summary> /// <param name="connectionName">Connection name in .config files (default is 'Ractor', it /// is also used as a prefix for zero-based distributed connections, e.g. Ractor.0 )</param> /// <param name="readOnlyShards"></param> /// <param name="guidType">Use AtEnd only for MS SQL Server, for MySQL and others DBMS without /// native GUID types use binary</param> /// <param name="migrationDataLossAllowed"></param> public DatabasePersistor(string connectionName = "Ractor", DbMigrationsConfiguration <DataContext> migrationConfig = null, DbMigrationsConfiguration <DistributedDataContext> distributedMigrationConfig = null, IEnumerable <byte> readOnlyShards = null, SequentialGuidType guidType = SequentialGuidType.SequentialAsBinary) { // Validate name presence _connectionName = Config.DataConnectionName(connectionName); // TODO delete this line when migrations are tested DataContext.UpdateAutoMigrations(_connectionName, migrationConfig); _guidType = guidType; if (readOnlyShards != null) { foreach (var readOnlyShard in readOnlyShards) { _readOnlyShards.Add(readOnlyShard); } } _shards = Config.DistibutedDataConnectionNames(_connectionName).ToDictionary(x => x.Key, y => y.Value); if (_readOnlyShards.Count >= _shards.Count) { throw new ArgumentException("Too few writable shards!"); } // check and register shards using (var ctx = GetContext()) { var two = ctx.Database.SqlQuery <int>("SELECT 1+1").SingleOrDefault(); // check DB engine is working if (two != 2) { throw new ApplicationException("Connection string is not working: " + connectionName); } } CheckShardsAndSetEpoch(distributedMigrationConfig); }
/// <summary> /// 生成连续 GUID /// </summary> /// <param name="guidType"></param> /// <param name="serviceProvider"></param> /// <returns></returns> public static Guid NextID(SequentialGuidType guidType = SequentialGuidType.SequentialAsString, IServiceProvider serviceProvider = default) { var sequentialGuid = (App.GetService(typeof(SequentialGuidIDGenerator), serviceProvider) as IDistributedIDGenerator); return((Guid)sequentialGuid.Create(new SequentialGuidSettings { GuidType = guidType })); }
private const int NumberOfBytesInData2 = 2; // Size of Data2 block of GUID /// <summary> /// Initializes a new instance of the <see cref="SequentialGuidFactory"/> class, which will generate keys as specified by <paramref name="sequentialGuidType"/>. /// </summary> /// <param name="sequentialGuidType">The type of sequential GUID values generated by the current instance.</param> /// <exception cref="ArgumentOutOfRangeException"><paramref name="sequentialGuidType"/> is not set to a recognized value.</exception> public SequentialGuidFactory(SequentialGuidType sequentialGuidType) { if (!Enum.IsDefined(typeof(SequentialGuidType), sequentialGuidType)) { throw new ArgumentOutOfRangeException(nameof(sequentialGuidType)); } SequentialGuidType = sequentialGuidType; }
/// <summary> /// Gets the next sequential guid, depending on where you are storing will dictate which type you want /// Note: When called within the same millisecond there is no guarntee it will be in sequence but it will be unique /// </summary> /// <param name="guidType"></param> /// <returns></returns> public static Guid Next(SequentialGuidType? guidType = null) { if (_random == null) { _random = new Random(_globalRandom.Next()); _count = (ushort)_random.Next(); } byte[] countBytes = BitConverter.GetBytes(_count++); byte[] randomBytes = new byte[10 - countBytes.Length]; _random.NextBytes(randomBytes); long timestamp = DateTime.UtcNow.Ticks / 10000L; byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; if (!guidType.HasValue) { guidType = DefaultType; } switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(countBytes, 0, guidBytes, 6, countBytes.Length); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6 + countBytes.Length, randomBytes.Length); // 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); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(countBytes, 0, guidBytes, 0, countBytes.Length); Buffer.BlockCopy(randomBytes, 0, guidBytes, countBytes.Length, randomBytes.Length); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return new Guid(guidBytes); }
/// <summary> /// 全局唯一Guid /// 参考abp中生成连续的guid改编而成 /// </summary> public static Guid Create(SequentialGuidType guidType) { var provider = GlobalConfigurations.Instance.GetGuidGeneratorProvider(guidType); if (provider == null) { throw new NotImplementedException("不支持的guidType"); } return(provider.Create()); }
public static Guid NewRandomBucketGuid(SequentialGuidType guidType = SequentialGuidType.SequentialAsString, DateTime?utcDateTime = null) { var bs = new byte[1]; bs[0] = 0; while (bs[0] == 0) { Rng.GetBytes(bs); } // 1-255 return(new Guid(GuidSequentialArray(bs[0], guidType, utcDateTime))); }
/// <summary> /// Returns a new GUID value which is sequentially ordered when formatted as /// a string, a byte array, or ordered by the least significant six bytes of the /// Data4 block, as specified by <paramref name="guidType" />. /// </summary> /// <param name="guidType"> /// Specifies the type of sequential GUID (i.e. whether sequential as a string, /// as a byte array, or according to the Data4 block. This can affect /// performance under various database types; see below. /// </param> /// <returns> /// A <see cref="Guid" /> structure whose value is created by replacing /// certain randomly-generated bytes with a sequential timestamp. /// </returns> public static Guid Create(SequentialGuidType guidType) { // We start with 16 bytes of cryptographically strong random data. byte[] randomBytes = new byte[10]; SequentialGuidGenerator.RandomGenerator.GetBytes(randomBytes); long timestamp = timestampProvider.GetTimestamp().Ticks / 10000L; // Then get the bytes byte[] timestampBytes = BitConverter.GetBytes(timestamp); // Since we're converting from an Int64, we have to reverse on // little-endian systems. if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: // For string and byte-array version, we copy the timestamp first, followed // by the random data. Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // If formatting as a string, we have to compensate for the fact // that .NET regards the Data1 and Data2 block as an Int32 and an Int16, // respectively. That means that it switches the order on little-endian // systems. So again, we have to reverse. if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAtEnd: // For sequential-at-the-end versions, we copy the random data first, // followed by the timestamp. Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
/// <summary> /// Generates a new GUID value which is sequentially ordered when formatted as a string, a byte array, or ordered by the least significant six bytes of the Data4 block, as specified by <paramref name="guidType" />. /// </summary> /// <param name="guidType">Specifies the type of sequential GUID (i.e. whether sequential as a string, as a byte array, or according to the Data4 block). This can affect performance under various database types.</param> /// <returns>A <see cref="Guid" /> structure whose value is created by replacing certain randomly-generated bytes with a sequential timestamp.</returns> private static Guid NewSequentialGuid(SequentialGuidType guidType) { // slower but more random byte[] randomBytes = new byte[10]; RandomGenerator.GetBytes(randomBytes); ////// faster but less random ////byte[] randomBytes = Guid.NewGuid().ToByteArray(); long timestamp = DateTime.UtcNow.Ticks / TicksFactor; byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); if (BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
/// <summary> /// Generates the GUIDs and displays them in the form. /// </summary> /// <param name="sender">The Generate button.</param> /// <param name="e">Additional information related to the event.</param> private void GenerateButton_Click(object sender, EventArgs e) { int count = 100; SequentialGuidType method = (SequentialGuidType)this.methodComboBox.SelectedItem; // Initialize the RTF text to enable color highlighting StringBuilder text = new StringBuilder(); text.Append("{\\rtf1\\ansi\\deff0\n{\\colortbl;\\red0\\green0\\blue0;\\red128\\green0\\blue0;}\n"); for (int i = 0; i < count; i++) { Guid guid = SequentialGuid.Create(method); string output = string.Empty; switch (method) { case SequentialGuidType.SequentialAsBinary: byte[] bytes = guid.ToByteArray(); foreach (byte b in bytes) { output += string.Format("{0:x2}", b); } output = "\\cf2\n" + output.Substring(0, 12) + "\n\\cf1\n" + output.Substring(12) + "\n\\line\n"; break; case SequentialGuidType.SequentialAsString: output = guid.ToString(); output = "\\cf2\n" + output.Substring(0, 13) + "\n\\cf1\n" + output.Substring(13) + "\n\\line\n"; break; case SequentialGuidType.SequentialAtEnd: output = guid.ToString(); output = "\\cf1\n" + output.Substring(0, 24) + "\n\\cf2\n" + output.Substring(24) + "\n\\line\n"; break; default: output = guid.ToString(); break; } text.Append(output); System.Threading.Thread.Sleep(1); } this.resultsTextBox.Rtf = text.ToString(); }
public Guid NewSequentialGuid(SequentialGuidType guidType) { byte[] randomBytes = new byte[10]; _rng.GetBytes(randomBytes); long timestamp = DateTime.UtcNow.Ticks / 10000L; byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: // For string and byte-array version, we copy the timestamp first, followed // by the random data. Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // If formatting as a string, we have to compensate for the fact // that .NET regards the Data1 and Data2 block as an Int32 and an Int16, // respectively. That means that it switches the order on little-endian // systems. So again, we have to reverse. if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAtEnd: // For sequential-at-the-end versions, we copy the random data first, // followed by the timestamp. Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
public static Guid NewSequentialGuid(SequentialGuidType guidType) { var randomBytes = new byte[10]; Rng.GetBytes(randomBytes); lock (Rng) { counter++; randomBytes[0] = (byte)counter; randomBytes[1] = (byte)(counter >> 8); } var timestamp = DateTime.Now.Ticks / 10000L; var timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } var guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // 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); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
public static long ExtractDateTimeTicks(byte[] guidBytes, SequentialGuidType guidType = SequentialGuidType.SequentialAsString) { byte[] timestampBytes = new byte[8]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(guidBytes, 0, timestampBytes, 2, 4); break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(guidBytes, 2, timestampBytes, 12, 4); break; } return(BitConverter.ToInt64(timestampBytes, 0)); }
internal static byte[] GuidSequentialArray(byte bucket, SequentialGuidType guidType, DateTime?utcDateTime = null) { //if (bucket > 63) throw new ArgumentOutOfRangeException("bucket", "Bucket is too large! 64 buckets ought to be enough for anybody!"); var bytes = new byte[16]; Rng.GetBytes(bytes); long ticks = utcDateTime.HasValue? utcDateTime.Value.Ticks : GetTicks(); // Convert to a byte array byte[] ticksArray = BitConverter.GetBytes(ticks); if (BitConverter.IsLittleEndian) { Array.Reverse(ticksArray); } // Copy the bytes into the guid switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Array.Copy(ticksArray, 1, bytes, 0, 7); // 7 bytes for ticks ~ 228 years // 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(bytes, 0, 4); Array.Reverse(bytes, 4, 2); Array.Reverse(bytes, 6, 2); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(ticksArray, 1, bytes, 9, 7); break; } var guidTypeByte = (byte)guidType; // first two bits for sequence type, other 6 bits for bucket bytes[8] = (byte)(((guidTypeByte & 3) << 6) | (bucket & 63)); return(bytes); }
public static Guid Generate(SequentialGuidType sequentialGuidType) { var randomBytes = new byte[10]; Rng.GetBytes(randomBytes); var timestamp = DateTime.UtcNow.Ticks / 10000L; var timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } var guidBytes = new byte[16]; switch (sequentialGuidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // If formatting as a string, we have to reverse the order // of the Data1 and Data2 blocks on little-endian systems. if (sequentialGuidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; default: throw new ArgumentOutOfRangeException(nameof(sequentialGuidType), sequentialGuidType, null); } return(new Guid(guidBytes)); }
public static Guid NewSequentialGuid(SequentialGuidType guidType = SequentialGuidType.SequentialAtEnd) { byte[] randomBytes = new byte[10]; _rng.GetBytes(randomBytes); long timestamp = DateTime.UtcNow.Ticks / 10000L; byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.NoSequential: return(Guid.NewGuid()); case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // 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); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
public static Guid NewGuid(SequentialGuidType guidType) { var randomBytes = new byte[10]; _random.NextBytes(randomBytes); //private static readonly RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider(); //_rng.GetBytes(randomBytes); var timestamp = DateTime.UtcNow.Ticks / 10000L; var timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } var guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // 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); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
internal static byte[] GuidSequentialArray(byte bucket, SequentialGuidType guidType, DateTime? utcDateTime = null) { //if (bucket > 63) throw new ArgumentOutOfRangeException("bucket", "Bucket is too large! 64 buckets ought to be enough for anybody!"); var bytes = new byte[16]; Rng.GetBytes(bytes); long ticks = utcDateTime.HasValue? utcDateTime.Value.Ticks : GetTicks(); // Convert to a byte array byte[] ticksArray = BitConverter.GetBytes(ticks); if (BitConverter.IsLittleEndian) { Array.Reverse(ticksArray); } // Copy the bytes into the guid switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Array.Copy(ticksArray, 1, bytes, 0, 7); // 7 bytes for ticks ~ 228 years // 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(bytes, 0, 4); Array.Reverse(bytes, 4, 2); Array.Reverse(bytes, 6, 2); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(ticksArray, 1, bytes, 9, 7); break; } var guidTypeByte = (byte) guidType; // first two bits for sequence type, other 6 bits for bucket bytes[8] = (byte)(( (guidTypeByte & 3) << 6 ) | (bucket & 63) ); return bytes; }
/// <summary> /// Gets the DateTime from sequential GUID. /// </summary> /// <param name="guid">The GUID.</param> /// <param name="guidType">Specifies the type of sequential GUID (i.e. whether sequential as a string, as a byte array, or according to the Data4 block). This can affect performance under various database types.</param> /// <returns> DateTime object expressed as the Coordinated Universal Time (UTC).</returns> private static DateTime GetTimestampFromGuid(Guid guid, SequentialGuidType guidType) { byte[] guidBytes = guid.ToByteArray(); byte[] timestampBytes = new byte[8]; switch (guidType) { case SequentialGuidType.SequentialAsString: if (BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } Buffer.BlockCopy(guidBytes, 0, timestampBytes, 2, 6); break; case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(guidBytes, 0, timestampBytes, 2, 6); break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(guidBytes, 10, timestampBytes, 2, 6); break; } if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } long dateTimeData = BitConverter.ToInt64(timestampBytes, 0) * TicksFactor; DateTime result = DateTime.FromBinary(dateTimeData); return(result); }
public static Guid Generate(SequentialGuidType sequentialGuidType) { var randomBytes = new byte[10]; Rng.GetBytes(randomBytes); var timestamp = DateTime.UtcNow.Ticks / 10000L; var timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } var guidBytes = new byte[16]; switch (sequentialGuidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // If formatting as a string, we have to reverse the order // of the Data1 and Data2 blocks on little-endian systems. if (sequentialGuidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; default: throw new ArgumentOutOfRangeException(nameof(sequentialGuidType), sequentialGuidType, null); } return new Guid(guidBytes); }
public static Guid Create(SequentialGuidType guidType = SequentialGuidType.SequentialAsString) { byte[] randomBytes = Guid.NewGuid().ToByteArray(); long timestamp = DateTime.UtcNow.Ticks / 10000L; var timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } var guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // 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); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; default: throw new Exception($"Case missing for {guidType}"); } return(new Guid(guidBytes)); }
public static Guid NewSequentialGuid(DateTime created, Guid sourceGuid, SequentialGuidType resultingGuidType) { var randomBytes = sourceGuid.ToByteArray(); var timestamp = created.Ticks / 10000L; var timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) Array.Reverse(timestampBytes); var guidBytes = new byte[16]; switch (resultingGuidType) { case (SequentialGuidType.SequentialAsString): case (SequentialGuidType.SequentialAsBinary): { Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // If formatting as a string, we have to reverse the order // of the Data1 and Data2 blocks on little-endian systems. if (resultingGuidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; } case (SequentialGuidType.SequentialAtEnd): { Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } } return new Guid(guidBytes); }
///<summary> /// Generates a GuidComb (COMBined GUID/timestamp). This is a Guid generation model, suggested by Jimmy Nilsson, where some bytes have been replaced by a timestamp-based value that is guaranteed to increase, but not decrease, with each new value generated. /// The goal is to remove the database performance limitations of using GUIDS as surrogate primary keys. ///</summary> ///<returns><see cref="Guid"/></returns> /// TODO: Determine the database type from service locator and predetermine what the guidType should be public static Guid Generate(SequentialGuidType guidType) { byte[] randomBytes = new byte[10]; _rng.GetBytes(randomBytes); // TODO: Implement DependencyInjection for date time instance //long timestamp = ServiceLocator.Current.GetInstance<IDateTimeProvider>().UtcNow.Ticks / 10000L; long timestamp = DateTime.UtcNow.Ticks / 10000L; byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // 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); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
public static Guid Create(SequentialGuidType guidType) { var randomBytes = new byte[10]; _RandomGenerator.GetBytes(randomBytes); var timestamp = DateTimeOffset.UtcNow.Ticks / 10000L; var timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } var guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
/// <summary> /// Initialize the generator. /// </summary> /// <param name="type">The sequential guid type.</param> public SequentialGuidGenerator(SequentialGuidType type) { _type = type; }
private static Guid NewGuid(SequentialGuidType guidType) { long timestamp = DateTime.UtcNow.Ticks / 10000L; //timestamp += Threading.Interlocked.Increment(ref guidSequenceNumber); byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = Guid.NewGuid().ToByteArray(); switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: 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); } break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return new Guid(guidBytes); }
public Guid Create(SequentialGuidType guidType) { // We start with 16 bytes of cryptographically strong random data. byte[] randomBytes = new byte[10]; _rng.GetBytes(randomBytes); // An alternate method: use a normally-created GUID to get our initial // random data: // byte[] randomBytes = Guid.NewGuid().ToByteArray(); // This is faster than using RNGCryptoServiceProvider, but I don't // recommend it because the .NET Framework makes no guarantee of the // randomness of GUID data, and future versions (or different // implementations like Mono) might use a different method. // Now we have the random basis for our GUID. Next, we need to // create the six-byte block which will be our timestamp. // We start with the number of milliseconds that have elapsed since // DateTime.MinValue. This will form the timestamp. There's no use // being more specific than milliseconds, since DateTime.Now has // limited resolution. // Using millisecond resolution for our 48-bit timestamp gives us // about 5900 years before the timestamp overflows and cycles. // Hopefully this should be sufficient for most purposes. :) long timestamp = DateTime.UtcNow.Ticks / 10000L; // Then get the bytes byte[] timestampBytes = BitConverter.GetBytes(timestamp); // Since we're converting from an Int64, we have to reverse on // little-endian systems. if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: // For string and byte-array version, we copy the timestamp first, followed // by the random data. Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // If formatting as a string, we have to compensate for the fact // that .NET regards the Data1 and Data2 block as an Int32 and an Int16, // respectively. That means that it switches the order on little-endian // systems. So again, we have to reverse. if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAtEnd: // For sequential-at-the-end versions, we copy the random data first, // followed by the timestamp. Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return new Guid(guidBytes); }
/// <summary> /// 获取有序的唯一ID。 /// </summary> /// <returns></returns> public static Guid GenerateComb(SequentialGuidType sequentialGuidType = SequentialGuidType.SequentialAtEnd) { return(SequentialGuidGenerator.NewSequentialGuid(sequentialGuidType)); }
/// <summary> /// Generate new Guid for a bucket /// </summary> public static Guid NewBucketGuid(byte bucket, SequentialGuidType guidType = SequentialGuidType.SequentialAsString, DateTime?utcDateTime = null) { return(new Guid(GuidSequentialArray(bucket, guidType, utcDateTime))); }
/// <summary> /// Generate a new Guid that will have the same bucket as the root Guid /// </summary> public static Guid NewBucketGuid(Guid rootGuid, SequentialGuidType guidType = SequentialGuidType.SequentialAsString) { return(new Guid(GuidSequentialArray(rootGuid.ToByteArray()[8], guidType))); }
public SequentialGuidIdGenerator(SequentialGuidType sequentialGuidType) { _sequentialGuidType = sequentialGuidType; }
/// <summary> /// Gets the DateTime from sequential GUID. /// </summary> /// <param name="guid">The GUID.</param> /// <param name="guidType">Specifies the type of sequential GUID (i.e. whether sequential as a string, as a byte array, or according to the Data4 block). This can affect performance under various database types.</param> /// <returns> DateTime object expressed as the Coordinated Universal Time (UTC).</returns> private static DateTime GetTimestampFromGuid(Guid guid, SequentialGuidType guidType) { byte[] guidBytes = guid.ToByteArray(); byte[] timestampBytes = new byte[8]; switch (guidType) { case SequentialGuidType.SequentialAsString: if (BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } Buffer.BlockCopy(guidBytes, 0, timestampBytes, 2, 6); break; case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(guidBytes, 0, timestampBytes, 2, 6); break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(guidBytes, 10, timestampBytes, 2, 6); break; } if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } long dateTimeData = BitConverter.ToInt64(timestampBytes, 0) * TicksFactor; DateTime result = DateTime.FromBinary(dateTimeData); return result; }
/// <summary> /// Returns a new GUID value which is sequentially ordered when formatted as /// a string, a byte array, or ordered by the least significant six bytes of the /// Data4 block, as specified by <paramref name="guidType" />. /// </summary> /// <param name="guidType"> /// Specifies the type of sequential GUID (i.e. whether sequential as a string, /// as a byte array, or according to the Data4 block. This can affect /// performance under various database types; see below. /// </param> /// <returns> /// A <see cref="Guid" /> structure whose value is created by replacing /// certain randomly-generated bytes with a sequential timestamp. /// </returns> /// <remarks> /// <para> /// This method creates a new GUID value which combines a random component /// with the current timestamp, also known as a COMB. The general concept /// is outlined in Jimmy Nilsson's article "The Cost of GUIDs as Primary Keys", /// and involves replacing either the least significant or most significant /// six bytes of the GUID with the current timestamp. This reduces the /// random component of the GUID from 16 bytes to 10 bytes, but this is /// still sufficient to prevent a collision under most real-world circumstances. /// </para> /// <para> /// The purpose of sequential GUIDs is not to promote the use of GUIDs as /// sortable entities. In fact, GUIDs generated very close together may /// have the same timestamp and are not guaranteed to be sequentially ordered /// at all. The intent is to increase performance when doing repeated /// inserts into database tables that have a clustered index on a GUID /// column, so that later entries do not have to be inserted into the middle /// of the table, but can simply be appended to the end. /// </para> /// <para> /// According to experiments, Microsoft SQL Server sorts GUID values using /// the least significant six bytes of the Data4 block; therefore, GUIDs being /// generated for use with SQL Server should pass a <paramref name="guidType" /> /// value of <c>SequentialAtEnd</c>. GUIDs generated for most other database /// types should be passed a <paramref name="guidType" /> value of /// <c>SequentialAsString</c> or <c>SequentialAsByteArray</c>. /// </para> /// <para> /// Various standards already define a time-based UUID; however, the /// format specified by these standards splits the timestamp into /// several components, limiting its usefulness as a sequential ID. /// Additionally, the format used for such UUIDs is not compatible /// with the GUID ordering on Microsoft SQL Server. /// </para> /// </remarks> public static Guid Create(SequentialGuidType guidType = SequentialGuidType.SequentialAsString) { // We start with 16 bytes of cryptographically strong random data. byte[] randomBytes = new byte[10]; SequentialGuid.RandomGenerator.GetBytes(randomBytes); // An alternate method: use a normally-created GUID to get our initial // random data: // byte[] randomBytes = Guid.NewGuid().ToByteArray(); // This is faster than using RNGCryptoServiceProvider, but I don't // recommend it because the .NET Framework makes no guarantee of the // randomness of GUID data, and future versions (or different // implementations like Mono) might use a different method. // Now we have the random basis for our GUID. Next, we need to // create the six-byte block which will be our timestamp. // We start with the number of milliseconds that have elapsed since // DateTime.MinValue. This will form the timestamp. There's no use // being more specific than milliseconds, since DateTime.Now has // limited resolution. // Using millisecond resolution for our 48-bit timestamp gives us // about 5900 years before the timestamp overflows and cycles. // Hopefully this should be sufficient for most purposes. :) long timestamp = DateTime.UtcNow.Ticks / 10000L; // Then get the bytes byte[] timestampBytes = BitConverter.GetBytes(timestamp); // Since we're converting from an Int64, we have to reverse on // little-endian systems. if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: case SequentialGuidType.SequentialAsBinary: // For string and byte-array version, we copy the timestamp first, followed // by the random data. Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); // If formatting as a string, we have to compensate for the fact // that .NET regards the Data1 and Data2 block as an Int32 and an Int16, // respectively. That means that it switches the order on little-endian // systems. So again, we have to reverse. if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAtEnd: // For sequential-at-the-end versions, we copy the random data first, // followed by the timestamp. Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return(new Guid(guidBytes)); }
/// <summary> /// Sets the default sequential GUID generation type. /// This method should be called at the application initialization. /// </summary> /// <param name="value">A sequential GUID generation type.</param> public static void SetDefaultSequentialGuidType(SequentialGuidType value) { defaultSequentialGuidType = value; }
/// <summary> /// 得到唯一标识提供者 /// </summary> /// <param name="sequentialGuidType">唯一标识类型</param> /// <returns></returns> public IGuidGeneratorProvider GetGuidGeneratorProvider(SequentialGuidType sequentialGuidType) { return(GetGuidGeneratorProvider(sequentialGuidType.Id)); }
public static Guid NewGuid(SequentialGuidType guidType = SequentialGuidType.SequentialAsString, DateTime? utcDateTime = null) { return new Guid(GuidSequentialArray(0, guidType, utcDateTime)); }
/// <summary> /// Generate a new Guid that will have the same bucket as the root Guid /// </summary> public static Guid NewBucketGuid(Guid rootGuid, SequentialGuidType guidType = SequentialGuidType.SequentialAsString) { return new Guid(GuidSequentialArray(rootGuid.ToByteArray()[8], guidType)); }
/// <summary> /// Generate new Guid for a bucket /// </summary> public static Guid NewBucketGuid(byte bucket, SequentialGuidType guidType = SequentialGuidType.SequentialAsString, DateTime? utcDateTime = null) { return new Guid(GuidSequentialArray(bucket, guidType,utcDateTime)); }
public static Guid NewRandomBucketGuid(SequentialGuidType guidType = SequentialGuidType.SequentialAsString, DateTime? utcDateTime = null) { var bs = new byte[1]; bs[0] = 0; while (bs[0] == 0) { Rng.GetBytes(bs); } // 1-255 return new Guid(GuidSequentialArray(bs[0], guidType, utcDateTime)); }
public static Guid NewRandomBucketGuid(SequentialGuidType guidType = SequentialGuidType.SequentialAsString, DateTime?utcDateTime = null) { return(new Guid(GuidSequentialArray((byte)Rng.Next(1, 256), guidType, utcDateTime))); }
public static Guid NewGuid(SequentialGuidType guidType = SequentialGuidType.SequentialAsString, DateTime?utcDateTime = null) { return(new Guid(GuidSequentialArray(0, guidType, utcDateTime))); }
public static Guid NewSequentialGuid(SequentialGuidType guidType) => NewSequentialGuid(DateTime.UtcNow, Guid.NewGuid(), guidType);
/// <summary> /// Generates a new GUID value which is sequentially ordered when formatted as a string, a byte array, or ordered by the least significant six bytes of the Data4 block, as specified by <paramref name="guidType" />. /// </summary> /// <param name="guidType">Specifies the type of sequential GUID (i.e. whether sequential as a string, as a byte array, or according to the Data4 block). This can affect performance under various database types.</param> /// <returns>A <see cref="Guid" /> structure whose value is created by replacing certain randomly-generated bytes with a sequential timestamp.</returns> private static Guid NewSequentialGuid(SequentialGuidType guidType) { // slower but more random byte[] randomBytes = new byte[10]; RandomGenerator.GetBytes(randomBytes); ////// faster but less random ////byte[] randomBytes = Guid.NewGuid().ToByteArray(); long timestamp = DateTime.UtcNow.Ticks / TicksFactor; byte[] timestampBytes = BitConverter.GetBytes(timestamp); if (BitConverter.IsLittleEndian) { Array.Reverse(timestampBytes); } byte[] guidBytes = new byte[16]; switch (guidType) { case SequentialGuidType.SequentialAsString: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); if (BitConverter.IsLittleEndian) { Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); } break; case SequentialGuidType.SequentialAsBinary: Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6); Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10); break; case SequentialGuidType.SequentialAtEnd: Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); break; } return new Guid(guidBytes); }