百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

在.Net 9中生成有序的Guid

mhr18 2025-02-09 13:18 24 浏览 0 评论

前言

在C#中叫Guid,其他语言中叫UUID,新的有序Guid就是使用UUID V7(第七版).

在项目中,我们是使用Guid作为主键,但有时候还需要有序的,在ABP中是提供生成有序的Guid,下面我们看看这几种生成Guid的方式.

示例

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using BenchmarkDotNet.Attributes;

namespace CSharpBenchmarks.SystemTest
{
	[MemoryDiagnoser]
	[DisassemblyDiagnoser(printSource: true)]
	public class GuidTest
	{
		public SequentialGuidGenerator sequentialGuidGenerator;

		[GlobalSetup]
		public void Init()
		{
			sequentialGuidGenerator = new();
		}

		[Params(1024, 2048, 4096)]
		public int Count { get; set; }

		[Benchmark(Baseline = true)]
		public void Test1()
		{
			List list = new List(Count);
			for (int i = 0; i < Count; i++)
			{
				list.Add(Guid.NewGuid()); //第一种:DotNet自带,无序的Guid
			}
		}

		[Benchmark]
		public void Test2()
		{
			List list = new List(Count);
			for (int i = 0; i < Count; i++)
			{
				list.Add(Guid.CreateVersion7()); //第二种: .Net 9增加的,有序的
			}
		}

		[Benchmark]
		public void Test3()
		{
			List list = new List(Count);
			for (int i = 0; i < Count; i++)
			{
				list.Add(sequentialGuidGenerator.Create()); //第三种: ABP生成有序的Guid
			}
		}
	}
}

/// 
/// Describes the type of a sequential GUID value.
/// 
public enum SequentialGuidType
{
	/// 
	/// The GUID should be sequential when formatted using the  method.
	/// Used by MySql and PostgreSql.
	/// 
	SequentialAsString,

	/// 
	/// The GUID should be sequential when formatted using the  method.
	/// Used by Oracle.
	/// 
	SequentialAsBinary,

	/// 
	/// The sequential portion of the GUID should be located at the end of the Data4 block.
	/// Used by SqlServer.
	/// 
	SequentialAtEnd
}

/// 
/// ABP 具体生成有序Guid的代码
/// 
public class SequentialGuidGenerator
{
	private static readonly RandomNumberGenerator RandomNumberGenerator = RandomNumberGenerator.Create();

	public SequentialGuidGenerator()
	{
	}

	public Guid Create()
	{
		return Create(SequentialGuidType.SequentialAsString);
	}

	public Guid Create(SequentialGuidType guidType)
	{
		// We start with 16 bytes of cryptographically strong random data.
		var randomBytes = new byte[10];
		RandomNumberGenerator.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);
	}
}

看看几种生成Guid的性能测试:

可以看到ABP中生成有序的Guid是这几种中耗时最多的,相当于.Net 中的生成无序Guid的两倍,如果不需要顺序的话,Guid.NewGuid()这种方式最好(这里不包含.Net framework,在.Net Core中对Guid有优化),如果需要顺序的话,且有需要性能的话,可以使用Guid.CreateVersion7()这种方式(不过这个需要.Net 9),短时间使用顺序的Guid还可以使用ABP的这种方式


个人能力有限,如果您发现有什么不对,请私信我

如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流

相关推荐

SQL入门知识篇(sql入门新手教程视频)

一、什么是数据库?什么是SQL?1、数据库:存放数据,可以很多人一起使用2、关系数据库:多张表+各表之间的关系3、一张表需要包含列、列名、行4、主键:一列(或一组列),其值能够唯一区分表中的每个行。5...

postgresql实现跨库查询-dblink的妙用

技术导语:用惯了oracle的dblink,转战postgresql,会一时摸不着头脑。本期就重点详细讲解postgresql如何安装dblink模块及如何使用dblink实现跨库查询。安装cont...

Oracle VM VirtualBox虚拟机软件(oracle vm virtualbox win10)

OracleVMVirtualBox是一款完全免费的虚拟机软件,下载银行有提供下载,软件支持安装windows、linux等多个操作系统,让用户可以在一台设备上实现多个操作系统的操作。同时软件有着...

开源 SPL 轻松应对 T+0(开源srs)

T+0问题T+0查询是指实时数据查询,数据查询统计时将涉及到最新产生的数据。在数据量不大时,T+0很容易完成,直接基于生产数据库查询就可以了。但是,当数据量积累到一定程度时,在生产库中进行大数据...

中小企业佳选正睿ZI1TS4-4536服务器评测

随着科技的不断发展,各行各业对于数据使用越加频繁,同时针对服务器的选择方面也就越来越多样化和细分化。那么对于我们用户来说,如何选择符合自身业务需求和最优性价比的产品呢?笔者将通过刚刚购买的这台服务器的...

MFC转QT:Qt基础知识(mfc和qt的区别)

1.Qt框架概述Qt的历史和版本Qt是一个跨平台的C++应用程序开发框架,由挪威公司Trolltech(现为QtCompany)于1991年创建。Qt的发展历程:1991年:Qt项目启动1995年...

数据库,QSqlTableModel(数据库有哪些)

QMYSQL——mysqlQSQLITE——sqliteQOICQ——orcale所需头文件.pro增加sql#include<QSqlDatabase>#include<Q...

python通过oledb连接dbf数据库(python连接jdbc)

起因:因为工作需要,需要读取dbf文件和系统数据中数据进行校对,因为知道dbf文件可以用sql查询,所以想能不能像mysql/oracle那样连接,再调用执行sql方法,通过一系列百度,尝试,最终通过...

Excel常用技能分享与探讨(5-宏与VBA简介 VBA与数据库)

在VBA(VisualBasicforApplications)中使用数据库(如Access、SQLServer、MySQL等)具有以下优点,适用于需要高效数据管理和复杂业务逻辑的场景:1....

Excel常用技能分享与探讨(5-宏与VBA简介 VBA与数据库-二)

以下是常见数据库软件的详细配置步骤,涵盖安装、驱动配置、服务启动及基本设置,确保VBA能够顺利连接:一、MicrosoftAccess适用场景:小型本地数据库,无需独立服务。配置步骤:安装Acces...

Windows Docker 安装(docker安装windows容器)

Docker并非是一个通用的容器工具,它依赖于已存在并运行的Linux内核环境。Docker实质上是在已经运行的Linux下制造了一个隔离的文件环境,因此它执行的效率几乎等同于所部署的L...

Windows下安装Ubuntu虚拟机方法(windows下安装ubuntu20)

在Windows下安装Ubuntu虚拟机。选择使OracleVMVirtualBox安装Ubuntu虚拟机。1.下载和安装OracleVMVirtualBox:访问OracleVMVir...

java入门教程1 - 安装和配置(win和linux)

windows安装和配置安装javahttps://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html目前大部分项目的...

Centos7 安装Tomcat8服务及配置jdk1.8教程

1、下载jdk1.8压缩包下载地址:https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.htmltom...

全网最完整的免费java教程讲义(一)——java配置和安装

一,安装Java1)安装JDK要学习和使用java,首先需要安装JDK(JavaDevelopemntKit),相当于java安装包。Java的下载页在甲骨文官网上:https://www.or...

取消回复欢迎 发表评论: