GUID 生成
GUID(全局唯一标识符)是数据库管理系统中常用的主键类型。ABP框架在其预构建的 应用模块 中优先采用GUID作为主键。同时,ICurrentUser.Id属性( 参见 )的类型也是GUID,这意味着ABP框架假定用户ID始终为GUID格式。
为何选择GUID?
GUID既有优势也有不足。网络上已有大量相关文章讨论此话题,因此我们不再赘述所有细节,仅列出最核心的优势:
- 跨数据库兼容:适用于所有数据库提供程序。
- 客户端生成主键:无需通过数据库往返生成ID值,可在插入新记录时提升性能,并在与数据库交互前预知主键值。
- 天然唯一性:在以下场景中具有显著优势:
- 需要与外部系统集成时
- 需要拆分或合并不同数据表时
- 构建分布式系统时
- 安全性更高:与自增ID相比,GID不可预测,在某些场景下更具安全性。
尽管存在一些不足(可通过网络搜索了解),但在设计ABP框架时,我们认为这些优势更为重要。
IGuidGenerator服务
GUID最显著的问题在于默认非顺序性。当将GUID作为主键并设置为表的聚集索引(默认配置)时,会导致插入性能显著下降(因为插入新记录可能需要重新排序现有记录)。
因此,切勿使用Guid.NewGuid()为实体创建ID!
针对此问题的解决方案是生成顺序GUID,ABP框架已内置该功能。IGuidGenerator服务可创建顺序GUID(默认通过SequentialGuidGenerator实现)。当需要手动设置实体ID时,请使用IGuidGenerator.Create()方法。
示例:创建具有GUID主键的实体
假设存在一个包含Guid类型主键的Product实体:
using System;
using Volo.Abp.Domain.Entities;
namespace AbpDemo
{
public class Product : AggregateRoot<Guid>
{
public string Name { get; set; }
private Product() { /* ORM/数据库提供程序使用此构造函数 */ }
public Product(Guid id, string name)
: base(id)
{
Name = name;
}
}
}
创建新产品时的实现:
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
namespace AbpDemo
{
public class MyProductService : ITransientDependency
{
private readonly IRepository<Product, Guid> _productRepository;
private readonly IGuidGenerator _guidGenerator;
public MyProductService(
IRepository<Product, Guid> productRepository,
IGuidGenerator guidGenerator)
{
_productRepository = productRepository;
_guidGenerator = guidGenerator;
}
public async Task CreateAsync(string productName)
{
var product = new Product(_guidGenerator.Create(), productName);
await _productRepository.InsertAsync(product);
}
}
}
该服务通过构造函数注入IGuidGenerator。若您的类为应用服务或继承自其他基类,可直接使用基类中的GuidGenerator属性(这是一个预注入的IGuidGenerator实例)。
配置选项
AbpSequentialGuidGeneratorOptions
AbpSequentialGuidGeneratorOptions是用于配置顺序GUID生成的选项类,包含以下属性:
DefaultSequentialGuidType(SequentialGuidType枚举类型):生成GUID值时使用的策略。
不同数据库提供程序处理GUID的方式存在差异,因此需根据数据库类型进行设置。SequentialGuidType枚举包含以下值:
SequentialAtEnd(默认值)适用于 SQL ServerSequentialAsString适用于MySQL和PostgreSQLSequentialAsBinary适用于Oracle
在模块的ConfigureServices方法中配置此选项(模块化基础),示例如下:
Configure<AbpSequentialGuidGeneratorOptions>(options =>
{
options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsBinary;
});
EF Core 集成包会根据相关数据库管理系统自动设置此选项。因此,若使用这些集成包,通常无需手动配置。
抠丁客


