平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“C#采用sqlSugar操作mysql数据库的实践教程”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
一、基本设置
1、安装依赖包
需安装3个依赖包,分别为mysqlConnector、sqlSugar、autofac
2、在appsettings.json中设置mysql的连接信息
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MySqlConnection": "Server=localhost;Database=net_demo;Uid=root;Pwd=123456;Port=3306;SslMode=None;"
}
}3、在入口文件中新建连接
using System.Text.Json;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using SqlSugar;
using study_demo10_orm.Utils;
namespace study_demo10_orm;
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// 配置 JSON 序列化:long 类型序列化为字符串,避免 JavaScript 精度丢失
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.WriteAsString;
});
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
// 配置swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 配置数据库连接
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer(container =>
{
// 使用Autofac 容器注册一个对象
container.Register(_ =>
{
var connectionString = builder.Configuration.GetConnectionString("MySqlConnection")
?? "Server=localhost;Database=test;Uid=root;Pwd=123456;Port=3306;";
var db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = connectionString, // 数据库地址字符串
DbType = DbType.MySql, // 指定数据库是mysql
IsAutoCloseConnection = true, // 自动关闭连接
InitKeyType = InitKeyType.Attribute,
MoreSettings = new ConnMoreSettings()
{
IsAutoRemoveDataCache = true // 数据变更时自动清理缓存
}
});
return db;
}).As().InstancePerLifetimeScope();
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
// 配置swagger
app.UseSwagger().UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
// 配置打印日志
app.Logger.LogInformation("程序已经启动,swagger地址:localhost:5179/swagger/index.html");
app.Run();
}
}
4、手动新建一个数据库表文件及手动新建一个数据模型
CREATE TABLE `account` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码',
`nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`phone` varchar(20) DEFAULT NULL COMMENT '手机号',
`status` bigint DEFAULT '1' COMMENT '状态 1正常 2禁用',
`created_at` bigint DEFAULT NULL COMMENT '创建时间',
`updated_at` bigint DEFAULT NULL COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '软删除',
PRIMARY KEY (`id`),
KEY `idx_account_deleted_at` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
using System;
using SqlSugar;
namespace Model.Entity
{
[SugarTable("account")]
public class AccountEntity
{
///
/// 主键
///
[SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true)]
public long Id { get; set; }
///
/// 用户名
///
[SugarColumn(ColumnName = "username")]
public string Username { get; set; }
///
/// 密码
///
[SugarColumn(ColumnName = "password")]
public string Password { get; set; }
///
/// 昵称
///
[SugarColumn(ColumnName = "nickname")]
public string Nickname { get; set; }
///
/// 头像
///
[SugarColumn(ColumnName = "avatar")]
public string Avatar { get; set; }
///
/// 邮箱
///
[SugarColumn(ColumnName = "email")]
public string Email { get; set; }
///
/// 手机号
///
[SugarColumn(ColumnName = "phone")]
public string Phone { get; set; }
///
/// 状态 1正常 2禁用
///
[SugarColumn(ColumnName = "status")]
public int? Status { get; set; }
///
/// 创建时间
///
[SugarColumn(ColumnName = "created_at")]
public long? CreatedAt { get; set; }
///
/// 更新时间
///
[SugarColumn(ColumnName = "updated_at")]
public long? UpdatedAt { get; set; }
///
/// 软删除
///
[SugarColumn(ColumnName = "deleted_at")]
public DateTime? DeletedAt { get; set; }
}
}
5、在控制器中采用SqlSugar来对数据库的操作
///
/// 接口
///
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class AccountController : ControllerBase
{
private readonly ISqlSugarClient _db;
///
/// 依赖注入
///
public AccountController(ISqlSugarClient db)
{
_db = db;
}
///
/// 创建账户
///
/// 创建账户的信息
///新创建的账户ID
///
/// 示例请求:
/// POST /api/account
/// {
/// "username": "testuser",
/// "password": "123456",
/// "nickname": "测试用户",
/// "email": "[email protected]",
/// "phone": "13800138000",
/// "status": 1
/// }
///
[HttpPost]
[ProducesResponseType(typeof(ApiResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResult), StatusCodes.Status400BadRequest)]
public async TaskCreate([FromBody] CreateAccountDTO dto)
{
// 参数校验
if (string.IsNullOrWhiteSpace(dto.Username))
{
return ResultHelper.Error("用户名不能为空");
}
if (string.IsNullOrWhiteSpace(dto.Password))
{
return ResultHelper.Error("密码不能为空");
}
// 检查用户名是否已存在
var exists = await _db.Queryable()
.Where(x => x.Username == dto.Username && x.DeletedAt == null)
.AnyAsync();
if (exists)
{
return ResultHelper.Error("用户名已存在");
}
// 创建实体
var entity = new AccountEntity
{
Username = dto.Username,
Password = dto.Password,
Nickname = dto.Nickname,
Avatar = dto.Avatar,
Email = dto.Email,
Phone = dto.Phone,
Status = dto.Status ?? 1,
CreatedAt = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
};
// 插入并获取返回的ID(雪花ID)
var insertResult = await _db.Insertable(entity).ExecuteReturnEntityAsync();
var id = insertResult.Id;
return ResultHelper.Success(new { Id = id });
}
}
二、设置由数据库文件来生成对应的数据模型
1、新建一个工具类
using System.Text;
using SqlSugar;
namespace study_demo10_orm.Utils;
///
/// 代码生成器工具类
/// 用于根据数据库表结构自动生成对应的实体类
///
public class Generator
{
///
/// 生成实体类文件
///
/// SqlSugar数据库实例
/// 输出目录路径
/// 命名空间名称
/// 指定要生成的表名数组,为空则生成所有表
public static void GenerateEntities(ISqlSugarClient db, string outputPath, string namespaceName, params string[] tables)
{
// 确保输出目录存在,不存在则创建
Directory.CreateDirectory(outputPath);
// 获取要生成的表列表:如果指定了表名则使用指定表,否则获取所有表
var tableList = tables?.Length > 0
? tables.ToList()
: db.DbMaintenance.GetTableInfoList().Select(t => t.Name).ToList();
// 遍历每个表生成对应的实体类
foreach (var table in tableList)
{
// 获取表的所有列信息
var columns = db.DbMaintenance.GetColumnInfosByTableName(table, false);
// 将表名转换为PascalCase作为类名(如下划线转驼峰)
var className = ToPascalCase(table) + "Entity";
var sb = new StringBuilder();
// 生成文件头部的警告注释(表示是自动生成的)
sb.AppendLine("//");
sb.AppendLine("// 此文件由代码生成器自动创建,请勿手动修改!");
sb.AppendLine();
sb.AppendLine("using System;");
sb.AppendLine("using SqlSugar;");
sb.AppendLine();
sb.AppendLine($"namespace {namespaceName}");
sb.AppendLine("{");
// 生成类声明和SugarTable特性
sb.AppendLine($" [SugarTable(\"{table}\")]");
sb.AppendLine($" public class {className}");
sb.AppendLine(" {");
// 遍历每列生成属性
foreach (var col in columns)
{
// 获取CLR类型和属性名
var clrType = GetClrType(col.DataType, col.IsNullable, col.DbColumnName);
var propertyName = ToPascalCase(col.DbColumnName);
// 添加XML文档注释(字段描述)
sb.AppendLine(" ///"); ");
sb.AppendLine($" /// {col.ColumnDescription}");
sb.AppendLine(" ///
// 构建SugarColumn特性参数
var attrParts = new List
{
$"ColumnName = \"{col.DbColumnName}\""
};
// 主键标记
if (col.IsPrimarykey) attrParts.Add("IsPrimaryKey = true");
// 注意:MySQL AUTO_INCREMENT 不需要 IsIdentity(那是雪花ID用的)
// 如果需要雪花ID,请在业务代码中手动设置
if (col.IsIdentity) attrParts.Add("IsIdentity = true");
// 输出SugarColumn特性
var attrStr = $"[SugarColumn({string.Join(", ", attrParts)})]";
sb.AppendLine($" {attrStr}");
sb.AppendLine($" public {clrType} {propertyName} {{ get; set; }}");
sb.AppendLine();
}
sb.AppendLine(" }");
sb.AppendLine("}");
// 写入文件
var filePath = Path.Combine(outputPath, $"{className}.cs");
File.WriteAllText(filePath, sb.ToString(), Encoding.UTF8);
Console.WriteLine($"Generated: {className}.cs");
}
Console.WriteLine($"Total generated: {tableList.Count} files");
}
///
/// 将下划线/连字符命名转换为PascalCase命名
/// 例如: user_info -> UserInfo, hello-world -> HelloWorld
///
/// 原始名称
///转换后的PascalCase名称
private static string ToPascalCase(string name)
{
if (string.IsNullOrWhiteSpace(name)) return name;
// 按下划线和连字符分割
var parts = name.Split(new[] { '_', '-' }, StringSplitOptions.RemoveEmptyEntries);
// 将每部分首字母大写后拼接
return string.Join("", parts.Select(p => char.ToUpper(p[0]) + p.Substring(1)));
}
///
/// 将数据库类型转换为C# CLR类型
///
/// 数据库中的数据类型
/// 是否可为空
///C#类型名称
private static string GetClrType(string dbType, bool isNullable, string columnName = "")
{
dbType = dbType.ToLower();
// 根据数据库类型映射到CLR类型
string result = dbType switch
{
"int" or "int unsigned" or "integer" => "int",
"bigint" or "bigint unsigned" => "long",
"tinyint" or "tinyint unsigned" => "int",
"smallint" or "smallint unsigned" => "short",
"bit" => "bool",
"float" or "float unsigned" => "float",
"double" or "double unsigned" => "double",
"decimal" or "numeric" or "dec" or "fixed" => "decimal",
"date" or "datetime" or "timestamp" or "time" => "DateTime",
"char" or "varchar" or "text" or "longtext" or "mediumtext" or "tinytext" or "nchar" or "nvarchar" => "string",
"blob" or "longblob" or "mediumblob" or "tinyblob" or "varbinary" or "binary" => "byte[]",
_ => "string"
};
// 根据字段名推断类型(当数据库类型不准确时)
var lowerName = columnName.ToLower();
if (result == "long" && lowerName.Contains("status"))
{
result = "int";
}
// 注意:不再强制 id 为 long,使用数据库实际类型
// 判断是否为值类型(值类型才能加可空标记?)
var isValueType = result != "string" && result != "byte[]";
// 值类型可空时加?后缀(如 int?)
if (isNullable && isValueType) result += "?";
return result;
}
}
2、在入口文件里面设置这个
...
// 配置数据库生成模型的
if (args.Contains("gen-model"))
{
using var scope = app.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService();
// 获取项目根目录的相对路径 (从 bin/Debug/net10.0 回退3级)
var projectRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", ".."));
var modelPath = Path.Combine(projectRoot, "Model", "Entity");
Generator.GenerateEntities(
db,
outputPath: modelPath,
namespaceName: "Model.Entity",
tables: Array.Empty()
);
return;
}
...
3、设置Makefile文件便于一件来操作
.PHONY: gen-model run
# 生成数据库模型
gen-model:
dotnet run --project . -- gen-model
# 运行项目
run:
dotnet run --project .
三、设置直接的时候输出打印的sql便于排查错误
1、直接在入库设置地方设置
...
// 配置数据库连接
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer(container =>
{
// 使用Autofac 容器注册一个对象
container.Register(_ =>
{
var connectionString = builder.Configuration.GetConnectionString("MySqlConnection")
?? "Server=localhost;Database=test;Uid=root;Pwd=123456;Port=3306;";
var db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = connectionString, // 数据库地址字符串
DbType = DbType.MySql, // 指定数据库是mysql
IsAutoCloseConnection = true, // 自动关闭连接
InitKeyType = InitKeyType.Attribute,
MoreSettings = new ConnMoreSettings()
{
IsAutoRemoveDataCache = true // 数据变更时自动清理缓存
}
});
// 配置SQL日志打印(点击可跳转到执行文件)
db.Aop.OnLogExecuting = (sql, pars) =>
{
// 获取调用栈信息
var stackTrace = new System.Diagnostics.StackTrace(true);
var frames = stackTrace.GetFrames();
string? filePath = null;
int lineNumber = 0;
string? methodName = null;
if (frames.Length > 0)
{
// 打印所有帧用于调试(注释掉正常后)
// for (int i = 0; i < Math.Min(frames.Length, 15); i++)
// {
// var frame = frames[i];
// Console.WriteLine($" Frame[{i}]: {frame.GetMethod()?.DeclaringType}.{frame.GetMethod()?.Name} at {frame.GetFileName()}:{frame.GetFileLineNumber()}");
// }
// 遍历找到第一个有文件信息的非 SqlSugar/Microsoft 帧
// 通常在 5-15 帧范围内能找到业务代码
for (int i = 0; i < frames.Length; i++)
{
var frame = frames[i];
var method = frame.GetMethod();
if (method == null) continue;
var declaringType = method.DeclaringType?.FullName ?? "";
var name = method.Name;
// 跳过内部框架类
if (declaringType.StartsWith("SqlSugar") ||
declaringType.StartsWith("Microsoft") ||
declaringType.StartsWith("System") ||
declaringType.StartsWith("Autofac"))
{
continue;
}
// 跳过编译器生成的匿名类和方法(如 lambda)
// 匿名方法通常名称包含 <> 或开头是 <
if (name.Contains('<') || name.Contains("<>"))
{
continue;
}
var fileName = frame.GetFileName();
var line = frame.GetFileLineNumber();
// 找到第一个有有效文件信息的帧
if (!string.IsNullOrEmpty(fileName))
{
filePath = fileName;
lineNumber = line > 0 ? line : 0;
methodName = $"{declaringType}.{name}";
break;
}
}
}
// Rider 格式输出: --> file.cs(line)
if (filePath != null && lineNumber > 0)
{
Console.WriteLine($" --> {filePath}({lineNumber}) [{methodName}]");
}
else if (filePath != null)
{
Console.WriteLine($" --> {filePath} [no line info] [{methodName}]");
}
// 打印可直接执行的SQL(将参数值替换到SQL中)
var executableSql = sql;
if (pars != null && pars.Length > 0)
{
foreach (var p in pars)
{
var value = p.Value;
if (value == null)
{
executableSql = executableSql.Replace(p.ParameterName, "NULL");
}
else if (value is string || value is DateTime)
{
executableSql = executableSql.Replace(p.ParameterName, $"'{value}'");
}
else
{
executableSql = executableSql.Replace(p.ParameterName, value.ToString() ?? "NULL");
}
}
}
Console.WriteLine($"SQL: {executableSql}");
Console.WriteLine();
};
// 错误日志
db.Aop.OnError = (exp) =>
{
Console.WriteLine($"SQL Error: {exp.Message}");
Console.WriteLine($"SQL: {exp.Sql}");
};
return db;
}).As().InstancePerLifetimeScope();
});
...
四、设置新建时间和更新时间
1、设置代码生成器中新建和更新时间字段
if (col.IsIdentity) attrParts.Add("IsIdentity = true");
// 自动时间戳字段处理
var lowerColName = col.DbColumnName.ToLower();
if (lowerColName == "created_at")
{
// 创建时间:插入时自动填充
attrParts.Add("InsertServerTime = true");
}
else if (lowerColName == "updated_at")
{
// 更新时间:插入和更新时自动填充
attrParts.Add("InsertServerTime = true");
attrParts.Add("UpdateServerTime = true");
}
2、重新生成的数据模型
///
/// 创建时间
///
[SugarColumn(ColumnName = "created_at", InsertServerTime = true)]
public DateTime CreatedAt { get; set; }
///
/// 更新时间
///
[SugarColumn(ColumnName = "updated_at", InsertServerTime = true, UpdateServerTime = true)]
public DateTime UpdatedAt { get; set; }
五、设置逻辑删除字段
1、定义一个接口
public interface ISoftDelete
{
DateTime? DeletedAt { get; set; }
}
2、自己定义的实体类都实现这个接口
namespace Model.Entity
{
[SugarTable("user")]
public class UserEntity:ISoftDelete
{
///
/// 主键id
///
[SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
}
}
3、在入口文件中采用过滤器
// 配置逻辑删除
db.QueryFilter.AddTableFilter(it => it.DeletedAt == null);
4、验证查询数据的时候,查看执行的sql,自动加上了逻辑删除的字段
[HttpGet("{id}")]
public async Task GetById(int id)
{
var task = await _db.Queryable().Where(x=>x.Id==id).FirstAsync();
return ResultHelper.Success(task);
}
5、如果想要查询逻辑删除的数据
[HttpGet("{id}")]
public async Task GetById(int id)
{
// var task = await _db.Queryable().Where(x=>x.Id==id).FirstAsync();
var task = await _db.Queryable()
.Filter(null,true)
.Where(x=>x.Id==id)
.FirstAsync();
return ResultHelper.Success(task);
}
6、采用逻辑删除数据(这里要采用更新操作)
[HttpDelete("{id}")]
public async Task Delete(int id)
{
await _db.Updateable()
.SetColumns(it => it.DeletedAt == DateTime.Now)
.Where(x => x.Id == id)
.ExecuteCommandAsync();
return ResultHelper.Success(new { Id = id });
}
到此这篇关于C#采用sqlSugar操作mysql数据库的完整教程的文章就介绍到这了,更多相关C# sqlSugar操作mysql数据库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多兼容脚本之家!
- C# SqlSugar批量执行SQL语句及批量更新实体对象的操作方法
- C#采用SqlSugarClient进行数据访问同时实现了统一的批量依赖注入(示例)
- C#连接Mysql实现增删改查的操作
- C#连接MySQL操作详细教程
- C#实现操作MySql数据层类MysqlHelper实例
- C#采用开源驱动连接操作MySQL数据库
- C#操作mysql数据库的代码实例

