基于SqlSugar的开发框架循序渐进介绍(4)– 在数据访问基类中对GUID主键进行自动赋值处理

虚幻大学 xuhss 407℃ 0评论

? 优质资源分享 ?

学习路线指引(点击解锁) 知识定位 人群定位
? Python实战微信订餐小程序 ? 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
?Python量化交易实战? 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

我们在设计数据库表的时候,往往为了方便,主键ID一般采用字符串类型或者GUID类型,这样对于数据库表记录的迁移非常方便,而且有时候可以在处理关联记录的时候,提前对应的ID值。但有时候进行数据记录插入的时候,往往忽略了对ID的赋值处理。为了便于使用或者允许自动赋值,我们可以在数据访问基类中对GUID主键进行自动赋值处理。

1、实体类主键属性的处理

在我们设计基于SqlSugar的框架的时候,实体类定义一个基类Entity,如下代码所示。

 [Serializable]
 public abstract class Entity : IEntity
 {
 /// 
 /// 实体类唯一主键
 /// 
 [SqlSugar.SugarColumn(IsPrimaryKey = true, ColumnDescription = "主键")]
 public virtual TPrimaryKey Id { get; set; }

一般可以扩展字符串,整形等等类型的实体类。

默认的Entity定义为整形的,如下所示。自增长的整形主键,不需要插入值,它在记录写入的时候获得对应的Id值。

 [Serializable]
 public abstract class Entity : Entity<int>, IEntity
 {
 /// 
        /// ID 主键,自增长类型
 /// 
        [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
 public override int Id { get; set; }
 }

对于字符型类型的ID键,可以在构造函数中对ID进行初始化。

    /// 
    /// 客户信息
 /// 继承自Entity,拥有Id主键属性
 /// 
    [SugarTable("T\_Customer")]
 public class CustomerInfo : Entity<string>
 {
 /// 
        /// 默认构造函数(需要初始化属性的在此处理)
 /// 
        public CustomerInfo()
 {
 this.Id = System.Guid.NewGuid().ToString();
 this.CreateTime = System.DateTime.Now;

 }

或者我们在数据插入一条新记录的时候,判断主键是否为空,然后赋值给它,或者唯一的GUID值。

使用Guid.NewGuid() 的处理,这样好处就是可以获得一个唯一的GUID值,而弊端是ID是无序的,没有先后顺序,对ID排序就是无意义了。

为了解决这个问题,我们还是引入Abp VNext的规则,生成一个有序的GUID值,同时在数据库访问基类,对插入记录、更新记录的时候,判断ID(对GUID类型或者字符串类型的主键ID)是否为空,为空则赋值一个有序的GUID给它,则可以完美解决问题了。

这样我们定义实体类的时候,ID值可以不初始化,让它保留位空,可以让用户主动设置值或者自动基类处理赋值。

    /// 
    /// 客户信息
 /// 继承自Entity,拥有Id主键属性
 /// 
    [SugarTable("T\_Customer")]
 public class CustomerInfo : Entity<string>
 {
 /// 
        /// 默认构造函数(需要初始化属性的在此处理)
 /// 
        public CustomerInfo()
 {
 this.CreateTime = System.DateTime.Now;
 }

2、基类判断ID是否为空并赋值

对于GUID或者字符串类型的ID值,为什么设置有序GUID,可以参考链接了解下:https://github.com/abpframework/abp/blob/48c52625f4c4df007f04d5ac6368b07411aa7521/docs/zh-Hans/Guid-Generation.md

一般情况下,我们利用SqlSugar插入一个新记录的时候,是如下代码

        /// 
        /// 创建对象
 /// 
        /// 实体对象
        /// 
        public virtual async Task<bool> InsertAsync(TEntity input)
 {
 return await EntityDb.InsertAsync(input); 
 }

而为了判断Id是否为空,我们需要对ID类型进行判断,判断是否字符串类型或者GUID类型,如果为空则自动赋值它,因此我们在插入前进行一个判断处理,如下代码所示。

        /// 
        /// 创建对象
 /// 
        /// 实体对象
        /// 
        public virtual async Task<bool> InsertAsync(TEntity input)
 {
 **SetIdForGuids**(input);//如果Id为空,设置有序的GUID值
            return await EntityDb.InsertAsync(input); 
 }

其中SetIdForGuids是获得有序GUID的值的函数。

        /// 
        /// 为新创建的实体对象,设置主键Id的值为有序的GUID值(GUID类型或者字符串类型试用)
 /// 
        public virtual void SetIdForGuids(TEntity entity)
 {
 if (entity is IEntity entityWithGuidId && entityWithGuidId.Id == Guid.Empty)
 {
 //默认的GUID类型
 var guidType = SequentialGuidType.SequentialAsString;

 switch(this.dbContext.DbType) //根据不同的数据库类型获取合适的生成序列方式
 {
 case SqlSugar.DbType.SqlServer:
 guidType = SequentialGuidType.SequentialAtEnd;
 break;
 case SqlSugar.DbType.MySql:
 case SqlSugar.DbType.PostgreSQL:
 guidType = SequentialGuidType.SequentialAsString;
 break;
 case SqlSugar.DbType.Oracle:
 guidType = SequentialGuidType.SequentialAsBinary;
 break;
 }

 var guid = GetSequentialGuid(guidType);
 entityWithGuidId.Id = guid;
 }
 else if (entity is IEntity<string> entityWithStringId && string.IsNullOrWhiteSpace(entityWithStringId.Id))
 {
 var guid = GetSequentialGuid(SequentialGuidType.SequentialAsString);
 entityWithStringId.Id = guid.ToString();
 }
 }

根据不同的数据库特性类型,构建不同的GUID值,如果是字符串的Id,我们统一采用 SequentialAsString 这个方式,这个也是支持字符串的常规排序处理,这样我们既获得了一个不重复的GUID值,也可以对ID进行排序,它是根据先后顺序排序的。

        /// 
        /// 获取可以生成连续的GUID
 /// 
        /// 
        protected Guid GetSequentialGuid(SequentialGuidType sequentialGuidType)
 {//使用指定序列创建的(生成连续的GUID)
 //参考链接了解细节:(https://github.com/abpframework/abp/blob/48c52625f4c4df007f04d5ac6368b07411aa7521/docs/zh-Hans/Guid-Generation.md)
            var options = new AbpSequentialGuidGeneratorOptions()
 {
 DefaultSequentialGuidType = sequentialGuidType
 //SequentialAtEnd(default) 用于SQL Server.
 //SequentialAsString 用于MySQL和PostgreSQL.
 //SequentialAsBinary 用于Oracle.
 };
 return new SequentialGuidGenerator(options).Create();
 }

添加几个字典类型(字符串ID)的记录进行测试。

442d741ead3cab5ef82889a79a2c8edb - 基于SqlSugar的开发框架循序渐进介绍(4)-- 在数据访问基类中对GUID主键进行自动赋值处理

可以看到ID的类型前缀部分是一样的,后面变化,以ID正序排序,是根据写入时间顺序处理的。

3119e5783856099752907fe058b69a0f - 基于SqlSugar的开发框架循序渐进介绍(4)-- 在数据访问基类中对GUID主键进行自动赋值处理

系列文章:

基于SqlSugar的开发框架的循序渐进介绍(1)--框架基础类的设计和使用

基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理

基于SqlSugar的开发框架循序渐进介绍(3)-- 实现代码生成工具Database2Sharp的整合开发

基于SqlSugar的开发框架循序渐进介绍(4)-- 在数据访问基类中对GUID主键进行自动赋值处理

转载请注明:xuhss » 基于SqlSugar的开发框架循序渐进介绍(4)– 在数据访问基类中对GUID主键进行自动赋值处理

喜欢 (30)

您必须 登录 才能发表评论!