.NETCore SqlSuagr 根据 mysql 数据表按顺序生成简单编号

目录

场景一:全局唯一序列号(Sequence)

[方案 A:利用 MySQL 的 AUTO_INCREMENT 属性(推荐)](#方案 A:利用 MySQL 的 AUTO_INCREMENT 属性(推荐))

[方案 B:使用专门的 Sequence 表(模拟 Oracle Sequence)](#方案 B:使用专门的 Sequence 表(模拟 Oracle Sequence))

场景二:基于已有数据生成新的顺序编号

[方案 A:使用 MySQL 的 ROW_NUMBER() 和 PARTITION BY (推荐)](#方案 A:使用 MySQL 的 ROW_NUMBER() 和 PARTITION BY (推荐))

[方案 B:在应用程序中生成(不推荐,除非数据量极小)](#方案 B:在应用程序中生成(不推荐,除非数据量极小))

[SqlSugar 针对 MySQL 的一些实用技巧](#SqlSugar 针对 MySQL 的一些实用技巧)

总结


如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

在 .NET 8 中使用 SqlSugar ORM 根据 MySQL 数据表按顺序生成编号,SqlSugar 在某些方面提供了更简洁的语法糖,尤其是在执行原生 SQL 和模拟数据库函数方面。

以下是针对前面提到的两种场景,使用 SqlSugar 的实现方式:


场景一:全局唯一序列号(Sequence)

SqlSugar 同样推荐使用 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_INCREMENT

public 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(); // ... 初始化你的 SqlSugarClient

var newItem = new YourTable

{

Column1 = "Some Value",

Column2 = 123

};

// Insertable().ExecuteCommandAsync() 会返回插入的行数

int rowsAffected = await dbContext.Insertable(newItem).ExecuteCommandAsync();

if (rowsAffected > 0)

{

// newItem.Id 现在已经包含了数据库生成的自增 ID

Console.WriteLine($"Generated ID: {newItem.Id}");

}

优点:

  • 最简单、性能最高,由数据库原生支持。
  • SqlSugar 对 AUTO_INCREMENT 的支持非常完善。
方案 B:使用专门的 Sequence 表(模拟 Oracle Sequence)

SqlSugar 同样支持模拟 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 Task<long> GetNextSequenceValue(string sequenceName, SugarTransactionApi transaction = null)

{

// 1. 获取序列当前值

var sequence = await _dbContext.Queryable<Sequence>()

.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 Task<long> GetNextSequenceValue(string sequenceName, SugarTransactionApi transaction)

{

// 1. 获取序列当前值

var sequence = await transaction.Queryable<Sequence>()

.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 列是 int

Column1 = "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 查询语句:

SELECT

t.*,

ROW_NUMBER() OVER (PARTITION BY t.Category ORDER BY t.CreatedAt ASC) AS SequentialNumber

FROM

YourTable 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 Task<List<YourTable>> GetItemsWithSequentialNumber(string category)

{

var dbContext = new SugarClient(); // 你的 SqlSugarClient

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}' -- 注意:此处使用字符串拼接,如果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.SqlQueryable<YourTable>(rawSql)

// .AddParameters(new { Category = category })

// .ToListAsync();

// 如果 SequentialNumber 不是数据库字段,而只是查询的别名,

// 你可能需要创建一个临时的DTO类来接收结果,或者直接从 SqlSugarResult 中解析。

// 简单起见,假设 YourTable 暂时不需要 SequentialNumber 属性,我们直接查询并用 SqlSugarResult 解析

var resultList = await dbContext.Ado.SqlQueryable<dynamic>(rawSql).ToListAsync(); // 使用dynamic接收

// 将 dynamic 结果转换为 List<YourTable> 并添加 SequentialNumber

var finalResult = new List<YourTable>();

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.Mapping<YourTable>().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 Task<List<YourTable>> AddSequentialNumbersInMemory(List<YourTable> 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.Queryable<YourTable>().ToListAsync();

// await AddSequentialNumbersInMemory(allItems);

// // 如果需要更新回数据库,需要进行后续的 Updateable 操作


SqlSugar 针对 MySQL 的一些实用技巧

  1. 获取最新插入 ID:
    • dbContext.Insertable(obj).ExecuteReturnIdentity(); 会直接返回插入对象的主键 ID。
    • dbContext.Insertable(obj).ExecuteCommand(); 返回影响行数,ID 会自动填充到 obj 对象中。
  2. 事务管理:
    • await db.Ado.BeginTransactionAsync();
    • await db.Ado.CommitTranAsync();
    • await db.Ado.RollbackTranAsync();
    • 在事务中执行操作时,需要将 SugarTransactionApi 传递给 Insertable、Updateable 等方法,或者直接使用 db.Ado.SugarTransaction 属性。
  3. 原生 SQL 执行:
    • dbContext.Ado.SqlQueryable<T>(sql).AddParameters(parameters).ToList(); 是执行复杂 SQL 的利器。

总结

  • 全局序列号: 优先使用 AUTO_INCREMENT,SqlSugar 的 IsIdentity = true 属性支持良好。如果需要模拟 Sequence,请务必在事务中操作,并理解其性能开销。
  • 生成顺序编号:
    • 查询时动态生成: 强烈建议使用 MySQL 的 ROW_NUMBER() 窗口函数,通过 SqlQueryable 执行,并使用 dynamic 或 DTO 来接收结果。
    • 插入/更新时固定编号: 需要先查询出当前最大的序号,再执行插入/更新。务必在事务中完成。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关推荐
yuniko-n1 小时前
【JUC】读写锁 StampedLock
java·1024程序员节
奔跑的呱呱牛1 小时前
开源了一个轻量级 Web 3D 模型检视 SDK:免后端纯前端解压 ZIP/OBJ,带工程测量与截面剖切
1024程序员节
知行产研1 小时前
湖州样板+团体标准,伯镭科技引领水泥矿山无人化
人工智能·科技·1024程序员节
小白今天也很酷1 小时前
MCXN947更新板载DAP_Link固件的方法
c语言·python·单片机·ubuntu·excel·1024程序员节
.道阻且长.1 小时前
Linux 基本开发工具:编辑器vim,配置vim
linux·运维·服务器·职场和发展·编辑器·vim·1024程序员节
AIyy8661 小时前
在线PPT生成工具功能观察:百度文库智能PPT、WPS AI与Kimi的侧重点
1024程序员节
小小AK1 小时前
线上退货单同步实战:从聚水潭到金蝶云星空的奇门对接策略
1024程序员节
攻城狮Soar1 小时前
详解volatile
开发语言·c++·1024程序员节
小羊没烦恼!1 小时前
.NET无侵入自动化探针原理和主流实现
运维·开发语言·javascript·python·自动化·.net·1024程序员节