.NETCore SqlSuagr 根据 mysql 数据表按顺序生成简单编号
目录场景一全局唯一序列号Sequence方案 A利用 MySQL 的 AUTO_INCREMENT 属性推荐方案 B使用专门的 Sequence 表模拟 Oracle Sequence场景二基于已有数据生成新的顺序编号方案 A使用 MySQL 的 ROW_NUMBER() 和 PARTITION BY 推荐方案 B在应用程序中生成不推荐除非数据量极小SqlSugar 针对 MySQL 的一些实用技巧总结如果您喜欢此文章请收藏、点赞、评论谢谢祝您快乐每一天。在 .NET 8 中使用SqlSugarORM 根据 MySQL 数据表按顺序生成编号SqlSugar在某些方面提供了更简洁的语法糖尤其是在执行原生 SQL 和模拟数据库函数方面。以下是针对前面提到的两种场景使用SqlSugar的实现方式场景一全局唯一序列号SequenceSqlSugar同样推荐使用 MySQL 的AUTO_INCREMENT属性。方案 A利用 MySQL 的AUTO_INCREMENT属性推荐1. MySQL 建表语句CREATE TABLE YourTable (Id INT AUTO_INCREMENT PRIMARY KEY,Column1 VARCHAR(255),Column2 INT);2.SqlSugar实体类public class YourTable{[SugarColumn(IsPrimaryKey true, IsIdentity true)] // IsIdentity true 对应 AUTO_INCREMENTpublic int Id { get; set; }public string Column1 { get; set; }public int Column2 { get; set; }}3.SqlSugar插入数据SqlSugar在插入时会自动处理IsIdentity true的列无需手动干预。// 假设 dbContext 是你的 SqlSugarClient 实例var dbContext new SugarClient(); // ... 初始化你的 SqlSugarClientvar newItem new YourTable{Column1 Some Value,Column2 123};// Insertable().ExecuteCommandAsync() 会返回插入的行数int rowsAffected await dbContext.Insertable(newItem).ExecuteCommandAsync();if (rowsAffected 0){// newItem.Id 现在已经包含了数据库生成的自增 IDConsole.WriteLine($Generated ID: {newItem.Id});}优点最简单、性能最高由数据库原生支持。SqlSugar对AUTO_INCREMENT的支持非常完善。方案 B使用专门的 Sequence 表模拟 Oracle SequenceSqlSugar同样支持模拟 Sequence。1. MySQL 建表语句Sequence 表CREATE TABLE Sequences (SequenceName VARCHAR(100) PRIMARY KEY,CurrentValue BIGINT NOT NULL,IncrementBy INT DEFAULT 1);INSERT INTO Sequences (SequenceName, CurrentValue, IncrementBy)VALUES (YourTableIdSeq, 0, 1);2.SqlSugar实体类public class Sequence{[SugarColumn(IsPrimaryKey true)]public string SequenceName { get; set; }public long CurrentValue { get; set; }public int IncrementBy { get; set; }}3.SqlSugar获取序列值并插入数据SqlSugar提供了更直接的执行 SQL 语句的方法并且可以通过ExecuteCommandAsync获取影响行数。public class SequenceService{private readonly ISugarQueryable _dbContext;public SequenceService(ISugarQueryable dbContext){_dbContext dbContext;}// 推荐使用事务来保证原子性public async Tasklong GetNextSequenceValue(string sequenceName, SugarTransactionApi transaction null){// 1. 获取序列当前值var sequence await _dbContext.QueryableSequence().SingleAsync(s s.SequenceName sequenceName);if (sequence null){throw new Exception($Sequence {sequenceName} not found.);}long nextValue sequence.CurrentValue sequence.IncrementBy;// 2. 更新序列值sequence.CurrentValue nextValue;// 标记为已修改以便 EF Core/SqlSugar 知道需要更新_dbContext.Updateable(sequence).ExecuteCommandAsync();return nextValue;}// 提供一个带有事务的重载public async Tasklong GetNextSequenceValue(string sequenceName, SugarTransactionApi transaction){// 1. 获取序列当前值var sequence await transaction.QueryableSequence().SingleAsync(s s.SequenceName sequenceName);if (sequence null){throw new Exception($Sequence {sequenceName} not found.);}long nextValue sequence.CurrentValue sequence.IncrementBy;// 2. 更新序列值sequence.CurrentValue nextValue;transaction.Updateable(sequence).ExecuteCommand(); // 在事务中更新return nextValue;}}4. .NET Core 插入数据时的调用using (var db new SugarClient()) // 你的 SqlSugarClient{// 开启事务await db.Ado.BeginTransactionAsync();try{var sequenceService new SequenceService(db); // 传递 ISugarQueryable// 使用带有事务的重载long newId await sequenceService.GetNextSequenceValue(YourTableIdSeq, db.Ado.SugarTransaction);var newItem new YourTable{Id (int)newId, // 假设 Id 列是 intColumn1 Sequence Value,Column2 456};await db.Insertable(newItem).ExecuteCommandAsync();// 提交事务await db.Ado.CommitTranAsync();Console.WriteLine($Generated ID: {newId});}catch (Exception ex){// 回滚事务await db.Ado.RollbackTranAsync();Console.WriteLine($Error: {ex.Message});}}优点SqlSugar的 API 简洁事务管理直观。缺点性能相对AUTO_INCREMENT较低。场景二基于已有数据生成新的顺序编号SqlSugar在处理原生 SQL 和窗口函数方面非常强大。方案 A使用 MySQL 的ROW_NUMBER()和PARTITION BY推荐1. MySQL 查询语句SELECTt.*,ROW_NUMBER() OVER (PARTITION BY t.Category ORDER BY t.CreatedAt ASC) AS SequentialNumberFROMYourTable t;2.SqlSugar查询SqlSugar提供了Queryable()扩展可以直接调用原生 SQL并且可以方便地映射到实体。public class YourTable{[SugarColumn(IsPrimaryKey true, IsIdentity true)]public int Id { get; set; }public string Column1 { get; set; }public int Column2 { get; set; }public string Category { get; set; }public DateTime CreatedAt { get; set; }// 注意这里不要直接定义 SequentialNumber 属性除非你确保数据库表也这么设计了// 如果只是查询时生成可以在返回结果时映射。}// ... 在你的 Service 或 Controller 中 ...public async TaskListYourTable GetItemsWithSequentialNumber(string category){var dbContext new SugarClient(); // 你的 SqlSugarClientvar rawSql $SELECTt.*,ROW_NUMBER() OVER (PARTITION BY t.Category ORDER BY t.CreatedAt ASC) AS SequentialNumberFROMYourTable tWHERE t.Category {category} -- 注意此处使用字符串拼接如果category来自用户输入需要做SQL注入防御;// 更安全的方式使用参数化查询// var rawSql // SELECT// t.*,// ROW_NUMBER() OVER (PARTITION BY t.Category ORDER BY t.CreatedAt ASC) AS SequentialNumber// FROM// YourTable t// WHERE t.Category Category// ;// var items await dbContext.SqlQueryableYourTable(rawSql)// .AddParameters(new { Category category })// .ToListAsync();// 如果 SequentialNumber 不是数据库字段而只是查询的别名// 你可能需要创建一个临时的DTO类来接收结果或者直接从 SqlSugarResult 中解析。// 简单起见假设 YourTable 暂时不需要 SequentialNumber 属性我们直接查询并用 SqlSugarResult 解析var resultList await dbContext.Ado.SqlQueryabledynamic(rawSql).ToListAsync(); // 使用dynamic接收// 将 dynamic 结果转换为 ListYourTable 并添加 SequentialNumbervar finalResult new ListYourTable();foreach (var row in resultList){var item new YourTable{Id (int)row.Id,Column1 row.Column1,Column2 (int)row.Column2,Category row.Category,CreatedAt (DateTime)row.CreatedAt// 无法直接映射到 YourTable 的 SequentialNumber 属性因为这个属性只在查询结果中存在};// 如果你需要这个值可以创建一个DTO// finalResult.Add(new YourTableDto { ..., SequentialNumber (int)row.SequentialNumber });// 简单演示直接用动态对象打印Console.WriteLine($ID: {row.Id}, Category: {row.Category}, SeqNum: {(int)row.SequentialNumber});// 如果真的需要为 YourTable 实体添加一个属性并在内存中填充// var mappedItem dbContext.MappingYourTable().Map(item, row); // 假设 SqlSugar有此方法// mappedItem.SequentialNumber (int)row.SequentialNumber; // 手动赋值// finalResult.Add(mappedItem);}return finalResult; // 返回你的DTO或处理过的实体列表}注意SqlSugar在SqlQueryable返回时可以直接映射到实体属性。如果你的实体类中没有SequentialNumber属性则需要创建 DTO。如果实体类中暂时没有该属性但你想在查询时生成并读取可能需要一个临时 DTO 或者直接使用dynamic。方案 B在应用程序中生成不推荐除非数据量极小SqlSugar同样可以通过 LINQ 语法在内存中生成。public async TaskListYourTable AddSequentialNumbersInMemory(ListYourTable items){var groupedItems items.GroupBy(item item.Category).Select(group group.OrderBy(item item.CreatedAt).ToList()).SelectMany(list list).ToList();int currentNumber 1;string currentCategory null;foreach (var item in groupedItems){if (currentCategory null || item.Category ! currentCategory){currentCategory item.Category;currentNumber 1;}else{currentNumber;}// 假设 YourTable 有 SequentialNumber 属性// item.SequentialNumber currentNumber;Console.WriteLine($Item ID: {item.Id}, Category: {item.Category}, SeqNum: {currentNumber});}return items;}// 调用示例// var db new SugarClient();// var allItems await db.QueryableYourTable().ToListAsync();// await AddSequentialNumbersInMemory(allItems);// // 如果需要更新回数据库需要进行后续的 Updateable 操作SqlSugar针对 MySQL 的一些实用技巧获取最新插入 IDdbContext.Insertable(obj).ExecuteReturnIdentity();会直接返回插入对象的主键 ID。dbContext.Insertable(obj).ExecuteCommand();返回影响行数ID 会自动填充到obj对象中。事务管理await db.Ado.BeginTransactionAsync();await db.Ado.CommitTranAsync();await db.Ado.RollbackTranAsync();在事务中执行操作时需要将SugarTransactionApi传递给Insertable、Updateable等方法或者直接使用db.Ado.SugarTransaction属性。原生 SQL 执行dbContext.Ado.SqlQueryableT(sql).AddParameters(parameters).ToList();是执行复杂 SQL 的利器。总结全局序列号优先使用AUTO_INCREMENTSqlSugar的IsIdentity true属性支持良好。如果需要模拟 Sequence请务必在事务中操作并理解其性能开销。生成顺序编号查询时动态生成强烈建议使用 MySQL 的ROW_NUMBER()窗口函数通过SqlQueryable执行并使用dynamic或 DTO 来接收结果。插入/更新时固定编号需要先查询出当前最大的序号再执行插入/更新。务必在事务中完成。如果您喜欢此文章请收藏、点赞、评论谢谢祝您快乐每一天。