技术归档文章随笔一句话导航搜索关于

ABP 是如何生成连续 GUID 的

日期: 2020-11-23 分组: .NET 标签: .NETABP 3分钟 515字

GUID 生成

GUID 是数据库管理系统中使用的常见主键类型。并且 ABP 框架假定用户 ID 始终是 GUID 类型。

IGuidGenerator 接口服务

GUID 的最主要的问题是默认情况下它不是连续的。 当将 GUID 用作主键并将其设置为表的索引(默认设置)时,会在插入时带来严重的性能问题(因为插入新记录可能需要对现有记录进行重新排序)。

所以,不要使用 Guid.NewGuid() 为您的实体创建 ID。ABP 框架提供 IGuidGenerator 服务用于创建连续的 GUID

1
using System;
2
using System.Threading.Tasks;
3
using Volo.Abp.DependencyInjection;
4
using Volo.Abp.Domain.Repositories;
5
using Volo.Abp.Guids;
6
7
namespace AbpDemo
8
{
9
public class MyProductService : ITransientDependency
10
{
11
private readonly IRepository<Product, Guid> _productRepository;
12
private readonly IGuidGenerator _guidGenerator;
13
14
public MyProductService(IRepository<Product, Guid> productRepository, IGuidGenerator guidGenerator)
15
{
10 collapsed lines
16
_productRepository = productRepository;
17
_guidGenerator = guidGenerator;
18
}
19
20
public async Task TestCreateGUIDAsync(string productName)
21
{
22
Guid guid = _guidGenerator.Create();
23
}
24
}
25
}
  • IGuidGenerator.Create() 用于创建连续的 Guid

配置

AbpSequentialGuidGeneratorOptions

AbpSequentialGuidGeneratorOptions 是用于配置顺序 GUID 生成的选项类,它具有一个枚举类型属性。 - DefaultSequentialGuidType(类型为 SequentialGuidType 的枚举):生成 GUID 值时使用的策略。

数据库在处理 GUID 时会有所不同,因此您应根据指定数据库进行设置 - SequentialAtEnd SQL Server - SequentialAsString MySQL or PostgreSQL - SequentialAsBinary Oracle

在模块的 ConfigureServices 中进行配置

1
Configure<AbpSequentialGuidGeneratorOptions>(options =>
2
{
3
options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary;
4
});

看源码

源码位置 Volo.Abp.Guids\Volo\Abp\Guids\SequentialGuidGenerator.cs

1
public Guid Create(SequentialGuidType guidType)
2
{
3
var randomBytes = new byte[10];
4
RandomNumberGenerator.GetBytes(randomBytes); // 先生成 10 字节的随机内容
5
6
long timestamp = DateTime.UtcNow.Ticks / 10000L;// 获取当前时间戳的值 / 10000
7
8
byte[] timestampBytes = BitConverter.GetBytes(timestamp);
9
10
if (BitConverter.IsLittleEndian)
11
{
12
Array.Reverse(timestampBytes);
13
}
14
15
byte[] guidBytes = new byte[16]; // 用于存储最终生成 Guid 的数组
27 collapsed lines
16
17
switch (guidType)
18
{
19
// 可以看到 MySQL、PostgreSQL、Oracle 他们三个对 Guid 的处理方式是一样的
20
case SequentialGuidType.SequentialAsString:
21
case SequentialGuidType.SequentialAsBinary:
22
23
Buffer.BlockCopy(timestampBytes, 2, guidBytes, 0, 6);
24
Buffer.BlockCopy(randomBytes, 0, guidBytes, 6, 10);
25
26
if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian)
27
{
28
Array.Reverse(guidBytes, 0, 4);
29
Array.Reverse(guidBytes, 4, 2);
30
}
31
32
break;
33
// SQL Server 独出一家
34
case SequentialGuidType.SequentialAtEnd:
35
36
Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10);
37
Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6);
38
break;
39
}
40
41
return new Guid(guidBytes);
42
}
  • 他的生成方式就是一个随机的 10 byte 的内容与当前时间 6 byte 相关的一个拼接,最终生成一个二进制长度为 128 位的 Guid。
人应当是有理想的.
文章目录