Sander.SequentialGuid 1.0.0

dotnet add package Sander.SequentialGuid --version 1.0.0
NuGet\Install-Package Sander.SequentialGuid -Version 1.0.0
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="Sander.SequentialGuid" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Sander.SequentialGuid --version 1.0.0
#r "nuget: Sander.SequentialGuid, 1.0.0"
#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 Sander.SequentialGuid as a Cake Addin
#addin nuget:?package=Sander.SequentialGuid&version=1.0.0

// Install Sander.SequentialGuid as a Cake Tool
#tool nuget:?package=Sander.SequentialGuid&version=1.0.0

GitHub license NetStandard 2.0

Introduction

By default, GUIDs are not alphanumerically continuous or sortable in a meaningful way.

A very common use for GUID is a primary key in the database - but with non-sequential GUIDs, it is not optimal to have the primary key as a clustered index. Using clustered index with nonsequential GUIDs can cause fragmentation and general performance issues.

To resolve this, SQL Server has NEWSEQUENTIALID, which creates alphanumerically sortable, sequential GUIDs. The downside ot this approach is that the application will have to wait the SQL Server to create the primary key before the entry becomes usable - and of course, there are other database engines that do not have similar functionality.

Windows has a native UuidCreateSequential function, which is not available on other .NET platforms.

SequentialGuid library is implemented as a .NET Standard 2.0 package, allowing creation of sortable GUIDs prior storing data in the database on any compatible platform. In addition, there are useful helper functions to convert to/from GUID or get specific character/byte.

SequentialGuid is aimed for high-performance applications, as other such libraries are often very underperforming or do not have comparable functionality. SequentialGuid performance is similar to the native UuidCreateSequential, see benchmarks.

Features

  • Flexible - define the starting GUID and step, or use the default values
  • Fast and memory-efficient - even on a laptop, SequentialGuid handles well over 25 million calls per second. This is comparable or better than the UuidCreateSequential performance
  • Thread-safe - create a single SequentialGuid instance for your web application and use it to generate sequential IDs
  • .NET Standard 2.0
  • Useful helper and extension methods, see below.

Using SequentialGuid

Create one instance of SequentialGuid per sequence (most likely per database table), sharing the instance among all the components which need that. SequentialGuid is fully thread-safe.

public EntityUpdater()
{
...
	var lastId = _myDatabaseProvider.GetLastId(); //get last primary key value (GUID) from the database
	_sequentialGuid = new SequentialGuid(lastId, 32); //initialize SequentialGuid with lastId as base value and step 32
	Trace.WriteLine(_sequentialGuid.Original); //trace the value that we used
}

public async Task<Guid> InsertEntity(ParentObject parent, ChildObject child)
{
	var nextId = _sequentialGuid.Next(); //get next sequential GUID, i.e. last + 32
	parent.Id = nextId; //set the primary key for DB
	//set up the child-parent relation without having to insert parent object first and wait for the result
	child.ParentId = nextId; 
	var task1 = _myDatabaseProvider.InsertAsync(parent); 
	var task2 = _otherDatabaseProvider.InsertChildAsync(child);
	await Task.WhenAll(task1, task2); //wait for both insertions to complete
	return nextId;
}

See SequentialGuidTests.cs for more examples.

Extension methods

Extension methods are implemented in class GuidExtensions.

  • GetCharacterAt(int position)- get a hexadecimal character at the specified position in GUID (0..31). As this does not rely on GUID being cast to string, it is much faster and uses less memory than default option - see the benchmark.
  • GetByteAt(int position) - get byte at the specified position (0..15). Somewhat faster than ToByteArray()[position], and uses ~30x less memory, see the benchmark. Note that this uses "Microsoft" byte order (see next method), to be compliant with ToByteArray() output.
  • ToCompliantByteArray() - .NET and Microsoft use different byte order inside GUID structure than other platforms (Java, Python and more). This returns byte array in the same order as Java/Python, and is suitable to be put to the data stores without native GUID/UUID implementation. Use GuidHelper.FromCompliantByteArray() to reverse the operation, as the new Guid(byte[] b) constructor expects ToByteArray()/Microsoft byte order.
  • ToBigInteger(bool isCompliant) - convert GUID to BigInteger. isCompliant = true is the default, and uses the same approach as ToCompliantByteArray() above, creating integer compatible with other systems and websites (e.g. http://guid-convert.appspot.com).
  • ToLongs() - convert GUID to (long, long) C# 7 tuple. Generally this should not be needed, but some Javascript libraries have used two integers to represent GUID, which doesn't exist as a native data type in JS.
Helper methods

Helper methods are in static class GuidHelper.

  • MaxValue - opposite of Guid.Empty, returns the maximum GUID value (ffffffff-ffff-ffff-ffff-ffffffffffff). Useful mainly for testing.
  • FromBigInteger(BigInteger integer, bool isCompliant) - creates GUID from BigInteger. If the BigInteger is too large (over 16 bytes), excess bytes are trimmed. Defaults to isCompliant = true, using Java/Python-compliant byte ordering.
  • FromDecimal(decimal dec) - create GUID from .NET decimal number
  • FromLongs(long first, long second) - create GUID from two Int64/long numbers. Generally this should not be needed, but some Javascript libraries have used two integers to represent GUID, which doesn't exist as a native data type in JS.
  • FromCompliantByteArray(byte[] bytes) - see ToCompliantByteArray() above.

Dependencies

  • System.Runtime.Numerics 4.3.0
  • System.ValueTuple 4.5.0
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  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 was computed.  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 was computed.  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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 9,729 3/15/2019