从零开始:用SugarColumn和SugarORM构建你的第一个C#数据库应用
当你第一次接触数据库应用开发时,可能会被繁琐的SQL语句和复杂的连接管理搞得晕头转向。这时候,ORM(对象关系映射)工具就像一位贴心的助手,帮你把面向对象的代码和关系型数据库之间的鸿沟轻松跨越。在C#生态中,SugarORM以其轻量级和易用性脱颖而出,特别适合刚入门的开发者快速上手。
SugarColumn作为SugarORM中的核心特性之一,让你能够通过简单的属性标注,就能精细控制实体类与数据库表之间的映射关系。想象一下,你不再需要手动编写创建表的SQL语句,也不再需要担心字段类型不匹配的问题——这一切都可以通过几行清晰的C#代码来完成。
本文将带你从零开始,一步步构建一个完整的C#数据库应用。无论你是刚接触C#的新手,还是有一定经验但想尝试SugarORM的开发者,都能从中获得实用的知识和技巧。我们会从环境配置开始,逐步深入到实体类定义、CRUD操作等核心内容,最后还会分享一些实际开发中的小技巧。
1. 环境准备与基础配置
在开始使用SugarORM之前,我们需要确保开发环境已经准备就绪。对于C#开发来说,Visual Studio无疑是最强大的IDE选择,但如果你更喜欢轻量级的工具,Visual Studio Code配合C#插件也能很好地完成任务。
首先,创建一个新的C#控制台应用程序项目。在Visual Studio中,可以通过"文件"→"新建"→"项目",然后选择"控制台应用(.NET Core)"模板来完成这一步骤。给项目取个有意义的名字,比如"FirstSugarApp"。
接下来,我们需要通过NuGet包管理器添加SugarORM的依赖。在解决方案资源管理器中右键点击项目,选择"管理NuGet程序包",然后搜索"SqlSugarCore"(SugarORM的核心包)。目前最新稳定版本是5.x系列,点击安装即可。
安装完成后,基本的项目结构应该如下所示:
FirstSugarApp/ ├── Program.cs ├── FirstSugarApp.csproj为了验证安装是否成功,可以在Program.cs文件中添加以下引用:
using SqlSugar;如果代码没有报错,说明SugarORM已经成功引入到项目中。接下来,我们需要配置数据库连接。SugarORM支持多种数据库,包括SQL Server、MySQL、PostgreSQL等。这里我们以SQLite为例,因为它不需要额外的服务器配置,非常适合学习和快速原型开发。
首先,添加SQLite的NuGet包:
- 再次打开NuGet包管理器
- 搜索"Microsoft.Data.Sqlite"
- 安装最新稳定版本
然后,在Program.cs中初始化SugarORM的SqlSugarClient:
var db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = "Data Source=./firstSugarDb.db", DbType = DbType.Sqlite, IsAutoCloseConnection = true, InitKeyType = InitKeyType.Attribute });这段代码创建了一个到SQLite数据库的连接,数据库文件将保存在项目目录下名为"firstSugarDb.db"的文件中。如果文件不存在,SugarORM会自动创建它。
提示:在实际项目中,建议将连接字符串放在配置文件中,而不是硬编码在代码里。这里为了演示简化了流程。
2. 定义实体类与SugarColumn详解
有了数据库连接后,下一步就是定义我们的数据模型。在ORM中,我们通过创建实体类来映射数据库中的表。SugarORM使用C#的特性(Attribute)来标记这些映射关系,其中SugarColumn是最常用的特性之一。
让我们创建一个简单的用户管理系统的数据模型。首先,在项目中添加一个名为"Models"的文件夹,然后创建一个新的类文件"User.cs"。
using SqlSugar; namespace FirstSugarApp.Models { [SugarTable("user")] // 指定映射到的表名 public class User { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } [SugarColumn(ColumnName = "user_name", Length = 50)] public string Name { get; set; } [SugarColumn(IsNullable = true)] public int? Age { get; set; } [SugarColumn(ColumnDataType = "varchar(100)")] public string Email { get; set; } [SugarColumn(IsIgnore = true)] public string TemporaryNote { get; set; } } }这个简单的User类展示了SugarColumn的多种用法:
- IsPrimaryKey:标记该属性为主键
- IsIdentity:表示主键是自增的
- ColumnName:指定数据库中的列名与属性名不同
- Length:设置字符串字段的最大长度
- IsNullable:允许字段为null
- ColumnDataType:精确控制数据库中的列类型
- IsIgnore:该属性不会被映射到数据库
SugarColumn还支持更多参数,下面是一个更全面的参数说明表格:
| 参数名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| IsPrimaryKey | bool | 是否为主键 | false |
| IsIdentity | bool | 是否自增 | false |
| ColumnName | string | 数据库列名 | 属性名 |
| ColumnDescription | string | 列描述 | null |
| ColumnDataType | string | 数据库类型 | 自动推断 |
| Length | int | 字段长度 | 0 |
| IsNullable | bool | 是否可为null | false |
| IsIgnore | bool | 是否忽略映射 | false |
| DecimalDigits | int | 小数位数 | 0 |
| OldColumnName | string | 旧列名(用于重命名) | null |
| IsOnlyIgnoreInsert | bool | 仅忽略插入 | false |
| IsOnlyIgnoreUpdate | bool | 仅忽略更新 | false |
在实际开发中,你不需要为每个属性都设置所有参数。SugarORM有很智能的默认行为,大多数情况下你只需要标记主键和需要特殊处理的字段即可。
3. 数据库表创建与基本CRUD操作
有了实体类定义后,我们可以让SugarORM帮我们创建对应的数据库表。这比手动编写SQL语句要简单和安全得多。
在Program.cs的Main方法中,添加以下代码:
// 创建数据库表 db.CodeFirst.InitTables(typeof(User));这行代码会根据User类的定义,在数据库中创建对应的表。如果表已经存在,SugarORM会比较模型和现有表的结构差异,必要时会提示你是否要执行迁移操作。
注意:在生产环境中,直接修改数据库结构需要谨慎。SugarORM提供了更安全的迁移工具,但对于初学者和小型项目,CodeFirst.InitTables已经足够。
现在,我们可以开始进行最基本的CRUD(创建、读取、更新、删除)操作了。下面是一些基本示例:
插入数据
// 插入单条记录 var userId = db.Insertable(new User() { Name = "张三", Age = 25, Email = "zhangsan@example.com" }).ExecuteReturnIdentity(); // 批量插入 var userList = new List<User> { new User { Name = "李四", Age = 30, Email = "lisi@example.com" }, new User { Name = "王五", Age = 28, Email = "wangwu@example.com" } }; db.Insertable(userList).ExecuteCommand();查询数据
// 查询所有记录 var allUsers = db.Queryable<User>().ToList(); // 条件查询 var youngUsers = db.Queryable<User>() .Where(u => u.Age < 30) .ToList(); // 分页查询 var pageUsers = db.Queryable<User>() .Where(u => u.Age > 20) .ToPageList(1, 10, ref totalCount);更新数据
// 更新单条记录 db.Updateable(new User() { Id = 1, Name = "张三丰", Age = 26 }).ExecuteCommand(); // 条件更新 db.Updateable<User>() .SetColumns(u => new User { Age = u.Age + 1 }) .Where(u => u.Age < 30) .ExecuteCommand();删除数据
// 根据主键删除 db.Deleteable<User>().In(1).ExecuteCommand(); // 条件删除 db.Deleteable<User>() .Where(u => u.Age > 60) .ExecuteCommand();这些基本操作涵盖了大多数日常开发需求。SugarORM的API设计非常直观,即使没有太多SQL知识,也能轻松理解这些操作对应的数据库行为。
4. 高级特性与性能优化
掌握了基本操作后,让我们看看SugarORM的一些高级特性,这些功能可以帮助你编写更高效、更简洁的代码。
事务处理
数据库事务对于保证数据一致性至关重要。SugarORM提供了简单的事务支持:
try { db.Ado.BeginTran(); // 一系列数据库操作 db.Insertable(new User { Name = "事务测试1" }).ExecuteCommand(); db.Insertable(new User { Name = "事务测试2" }).ExecuteCommand(); db.Ado.CommitTran(); } catch (Exception) { db.Ado.RollbackTran(); throw; }复杂查询
SugarORM支持复杂的查询构建,几乎可以满足所有SQL查询需求:
// 多表联查 var query = db.Queryable<User, Order>((u, o) => new JoinQueryInfos( JoinType.Left, u.Id == o.UserId)) .Where((u, o) => u.Age > 20) .Select((u, o) => new { u.Name, o.OrderNo }) .ToList(); // 分组查询 var ageGroups = db.Queryable<User>() .GroupBy(u => u.Age) .Select(u => new { Age = u.Age, Count = SqlFunc.AggregateCount(u.Id) }) .ToList();性能优化技巧
- 批量操作:对于大量数据操作,总是使用批量方法而非循环单条操作
- 异步支持:所有主要方法都有异步版本,适合Web应用
- 查询过滤器:可以定义全局过滤条件,如软删除
- 二级缓存:减少重复查询对数据库的压力
// 异步操作示例 var asyncUsers = await db.Queryable<User>() .Where(u => u.Age > 20) .ToListAsync(); // 使用查询过滤器 db.QueryFilter.Add(new TableFilterItem<User>(u => u.IsDeleted == false)); // 之后的所有查询都会自动加上这个条件实体关系映射
SugarORM支持一对一、一对多等关系映射:
[SugarTable("order")] public class Order { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } public string OrderNo { get; set; } [SugarColumn(IsNullable = false)] public int UserId { get; set; } [Navigate(NavigateType.OneToOne, nameof(UserId))] public User User { get; set; } }这样查询订单时,可以自动加载关联的用户信息:
var orders = db.Queryable<Order>() .Includes(o => o.User) // 自动加载User .ToList();5. 实际开发中的经验分享
在实际项目中使用SugarORM一段时间后,我积累了一些值得分享的经验:
实体类设计的最佳实践
- 为所有实体添加一个基类,包含公共字段如Id、CreateTime等
- 合理使用partial类将大型实体拆分到多个文件
- 为常用查询条件创建扩展方法
public abstract class EntityBase { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } [SugarColumn(ColumnName = "create_time")] public DateTime CreateTime { get; set; } = DateTime.Now; [SugarColumn(ColumnName = "update_time")] public DateTime UpdateTime { get; set; } = DateTime.Now; } public partial class User : EntityBase { // 基础字段 } public static class UserQueryExtensions { public static ISugarQueryable<User> ActiveUsers(this ISugarQueryable<User> query) { return query.Where(u => u.IsActive); } }处理数据库迁移
对于生产环境,直接使用CodeFirst.InitTables可能不够安全。建议:
- 开发环境可以使用InitTables快速迭代
- 测试和生产环境使用迁移工具
- 重大变更考虑手动编写迁移脚本
调试与日志
SugarORM提供了详细的SQL日志功能,对调试非常有帮助:
db.Aop.OnLogExecuting = (sql, pars) => { Console.WriteLine(sql); Console.WriteLine(string.Join(",", pars?.Select(p => p.ParameterName + "=" + p.Value))); };性能监控
对于关键业务操作,监控SQL执行时间:
db.Aop.OnLogExecuting = (sql, pars) => { Stopwatch sw = new Stopwatch(); sw.Start(); }; db.Aop.OnLogExecuted = (sql, pars) => { sw.Stop(); Console.WriteLine($"执行时间:{sw.ElapsedMilliseconds}ms"); };在最近的一个项目中,我们使用SugarORM处理了每天数十万次的数据库操作,通过合理的优化和缓存策略,系统保持了良好的响应速度。特别是在处理复杂报表查询时,SugarORM的灵活查询构建器让我们能够快速调整查询逻辑而无需重写大量SQL代码。