Medo.Uuid7.EntityFrameworkCore 1.8.1

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Medo.Uuid7.EntityFrameworkCore --version 1.8.1                
NuGet\Install-Package Medo.Uuid7.EntityFrameworkCore -Version 1.8.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Medo.Uuid7.EntityFrameworkCore" Version="1.8.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Medo.Uuid7.EntityFrameworkCore --version 1.8.1                
#r "nuget: Medo.Uuid7.EntityFrameworkCore, 1.8.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Medo.Uuid7.EntityFrameworkCore as a Cake Addin
#addin nuget:?package=Medo.Uuid7.EntityFrameworkCore&version=1.8.1

// Install Medo.Uuid7.EntityFrameworkCore as a Cake Tool
#tool nuget:?package=Medo.Uuid7.EntityFrameworkCore&version=1.8.1                

Medo.Uuid7.EntityFrameworkCore

The UUID7 library is an implementation of the UUID version 7 variant as defined in the new UUID specification, which introduces a time-ordered value field derived from the timestamp source. It offers improved entropy characteristics compared to versions 1 or 6 of the UUID standard. The inherent monotonicity of UUID version 7 makes it an excellent choice for utilization as a binary database key.

If you don't need Entity Framework support, you can use Medo.Uuid7.

Features:

  • Time-ordered value field: UUID7 utilizes the widely implemented Unix Epoch timestamp source to generate a time-ordered value field. This enables easy sorting and indexing of resources based on their creation time.
  • Enhanced entropy characteristics: UUID7 provides improved entropy characteristics over UUID versions 1 or 6. The inclusion of the timestamp ensures a high level of uniqueness, minimizing the chances of collisions across different systems or instances.
  • Multiple string representations: In addition to the standard UUID string formatting, library also offers ID22 and ID25 string conversions.
  • Wide compatibility: Support for .NET Standard 2.0 makes this library compatible with .NET Framework 4.6.1 or higher.
  • High performance: Speed comparable to the optimized built-in GUID generator in both single-threaded and multi-threaded scenarios under Windows and Linux.
  • Hardware acceleration: Vector128 support for Equals method.
  • Microsoft SQL Server support: Separate methods for "LE" Guid creation.
  • .NET 8 AOT support

You can find packaged library at NuGet.

Usage

To generate a new database-friendly UUID v7, simply call NewUuid7 method:

using System;
using Medo;

var uuid = Uuid7.NewUuid7();  // or 'Uuid7.NewGuid()'
Console.WriteLine($"UUID : {uuid}");

Alternatively, if a fully random UUID v4 is desired, call NewUuid4 method:

using System;
using Medo;

var uuid = Uuid7.NewUuid4();
Console.WriteLine($"UUID : {uuid}");

If higher performance is needed and per-thread seqencing is sufficient, you can instantiate UUID directly:

using System;
using Medo;

var uuid = new Uuid7();
Console.WriteLine($"UUID : {uuid}");

Configuration

Disable RNG Buffering

Buffering of random numbers significantly increases performance at the cost of less frequent but bigger requests toward random number generator. If buffering is not desired (e.g. only a small count of UUIDs is needed), you can disable it using UUID7_NO_RANDOM_BUFFER preprocessor constant.

<PropertyGroup>
    <DefineConstants>UUID7_NO_RANDOM_BUFFER</DefineConstants>
</PropertyGroup>

Note that this will decrease performance significantly.

UUID Format

The format of UUIDv7 is as specified below.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           unix_ts_ms                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          unix_ts_ms           |  ver  |       rand_a          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|                        rand_b                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            rand_b                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

unix_tx_ms: 48 bit big-endian unsigned number of Unix epoch timestamp.

ver: 4 bit UUIDv7 version. Always 0111.

rand_a: 12 bits of pseudo-random data.

var: 2 bit variant. Always 10.

rand_b: Additional 62 bits of pseudo-random data.

Implementation

As monotonicity is important for UUID version 7 generation, this implementation implements most of monotonic random counter recommendations.

Implementation uses randomly seeded 26 bit monotonic counter (25 random bits + 1 rollover guard bit) with a 4-bit increment.

Counter uses 12-bits from rand_a field and it "steals" 14 bits from rand_b field. Counter will have its 25 bits fully randomized each millisecond tick. Within the same millisecond tick, counter will be randomly increased using 4 bit increment.

In the case of multithreaded use, the counter seed is different for each thread.

In the worst case, this implementation guarantees at least 2^21 monotonically increasing UUIDs per millisecond. Up to 2^23 monotonically increasing UUID values per millisecond can be expected on average. Monotonic increase for each generated value is guaranteed on per thread basis.

The last 48 bits are filled with random data that is different for each generated UUID.

As each UUID uses 48 random bits in addition to 25 random bits from the seeded counter, this means we have at least 73 bits of entropy (without taking 48-bit timestamp into account).

With those implementation details in mind, the final layout is defined as below.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           unix_ts_ms                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          unix_ts_ms           |  ver  |        counter        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|          counter          |            random             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            random                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

unix_tx_ms: 48 bit big-endian unsigned number of Unix epoch timestamp.

ver: 4 bit UUIDv7 version. Always 0111.

var: 2 bit variant. Always 10.

counter: 26 bit big-endian unsigned counter.

random: 48 bits of random data.

Textual Representation

While this UUID should be handled and stored in its binary 128 bit form, it's often useful to provide a textual representation.

UUID Format

This is a standard hexadecimal representation of UUID with dashes separating various components. Please note that this component separation doesn't necessarily correlate with any internal fields.

Example:

0185aee1-4413-7023-9109-bde493efe31d

Id25

Alternative string representation is Id25 (Base-35), courtesy of stevesimmons. While I have seen similar encodings used before, his implementation is the first one I saw being used on UUIDs. Since it uses only numbers and lowercase characters, it actually retains lexicographical sorting property the default UUID text format has.

UUID will always fit in 25 characters.

Example:

0672016s27hx3fjxmn5ic1hzq

Id22

If more compact string representation is needed, one can use Id22 (Base-58) encoding. This is the same encoding Bitcoin uses for its keys.

UUID will always fit in 22 characters.

Example:

1BuKkq6yWzmN2fCaHBjCRr
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Medo.Uuid7.EntityFrameworkCore:

Package Downloads
Platter.DomainCore

DomainCore

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.0-beta3 60 11/23/2024
3.0.0-beta2 63 11/22/2024
3.0.0-beta1 57 11/19/2024
2.1.1 142 11/9/2024
2.1.0 91 11/6/2024
2.0.0 7,925 6/30/2024
1.9.1 6,721 1/21/2024
1.9.0 165 1/7/2024
1.8.2 173 11/25/2023
1.8.1 131 11/15/2023
1.8.0 120 11/15/2023
1.7.0 241 7/7/2023
1.6.1 168 7/5/2023
1.6.0 176 7/4/2023

## Changelog

### [1.8.1] - 2023-11-15

- Fixed .NET 8 AOT compilation support


### [1.8.0] - 2023-11-15

- Added .NET 8 AOT compilation support
- ToString optimizations


### [1.7.0] - 2023-07-06

- Improved performance
- Added ISpanFormattable interface
- Added ISpanParsable interface
- Added format specifiers for Id25 ('5') and Id22 ('2')
- Added Fill method for .NET Standard 2.0 targets


### [1.6.1] - 2023-07-04

- Static methods use locks to allow for sequencing even when called from
 different threads (e.g. usage with async)


### [1.6.0] - 2023-07-02

- Added Entity Framework Core version (separate NuGet package)
- Added NewGuid() method
- Added MS SQL Guid format support (NewGuidMsSql and ToGuidMsSql)
- Added implicit conversion from and to Guid


### [1.5.0] - 2023-06-29

- Added TryWriteBytes method
- Updated GetHashCode method
- HW acceleration for Equals method


### [1.4.0] - 2023-06-19

- Major optimizations (buffered RandomNumberGenerator calls)
- Changed NuGet package name to Medo.Uuid7
- Obsoleted NuGet package Uuid7


### [1.3.5] - 2023-06-19

- Updated readme


### [1.3.4] - 2023-06-12

- Minor optimizations
- Updated readme


### [1.3.3] - 2023-06-07

- Minor optimizations
- Added fully random v4 UUID support


### [1.3.2] - 2023-05-17

- .NET Standard 2.0 support
- ToString() performance optimizations


### [1.3.1] - 2023-05-16

- Performance optimizations


### [1.3.0] - 2023-04-30

- Added IFormattable interface
- Fixed EF NullReferenceException when CompareArrays gets a null input


### [1.2.0] - 2023-04-12

- Timestamps are monotonically increasing even if time goes backward


### [1.1.1] - 2023-01-14

- Fixed monotonicity bug


### [1.1.0] - 2023-01-14

- Using random increment (was tick based before)
- Performance improvements


### [1.0.2] - 2023-01-13

- Fixed docs


### [1.0.1] - 2023-01-13

- Added readme


### [1.0.0] - 2023-01-13

- First release



[unreleased]: https://github.com/medo64/Medo.uuid7
[1.7.0]: Medo.Uuid7/1.7.0
[1.6.1]: Medo.Uuid7/1.6.1
[1.6.0]: Medo.Uuid7/1.6.0
[1.5.0]: Medo.Uuid7/1.5.0
[1.4.0]: Medo.Uuid7/1.4.0
[1.3.5]: Uuid7/1.3.5
[1.3.4]: Uuid7/1.3.4
[1.3.3]: Uuid7/1.3.3
[1.3.2]: Uuid7/1.3.2
[1.3.1]: Uuid7/1.3.1
[1.3.0]: Uuid7/1.3.0
[1.2.0]: Uuid7/1.2.0
[1.1.1]: Uuid7/1.1.1
[1.1.0]: Uuid7/1.1.0
[1.0.2]: Uuid7/1.0.2
[1.0.1]: Uuid7/1.0.1
[1.0.0]: Uuid7/1.0.0