
这篇文章从新手友好的入门步骤讲起:教你如何快速配置环境、初始化SqlSugar连接,甚至连实体类与MongoDB集合的映射都给了清晰示例;接着深入核心功能——用几行代码就能实现CRUD操作、用链式查询简化复杂条件、用事务保证数据一致性,每一步都有具体演示;最后还附上实战案例,比如搭建一个简单的用户管理系统,把SqlSugar用到真实业务场景里,帮你摸透它的实际价值。
不管你是刚接触MongoDB的新手(怕踩坑),还是想优化现有代码的老司机(想提效),都能从这里学到能直接用的技巧。 我们就把SqlSugar的用法拆解得明明白白,帮你彻底告别MongoDB开发的“重复劳动”。
你有没有过写MongoDB原生驱动代码的崩溃时刻?比如为了查一条带条件的数据,要拼半天FilterDefinition
,或者更新数据时得手动映射实体属性到BsonDocument
,写完还要反复检查有没有漏字段——我去年帮做电商系统的朋友调代码,他那堆MongoDB操作类快有两百行,改个需求得翻半小时。直到他试了SqlSugar.Mongo这个全新的ORM框架,原来要写十行的查询代码,现在用链式语法一行就搞定,那堆操作类直接缩到了三十行——这不是夸张,是我亲眼看着他删代码时的“爽感”。
SqlSugar凭什么能解决MongoDB开发的“低效痛点”
要搞懂SqlSugar的价值,得先回到MongoDB开发的核心痛点——“对象-文档映射(ODM)的繁琐”和“查询语法的割裂感”。
MongoDB是文档型数据库,原生驱动要求你把实体类转成BsonDocument
才能操作,但这个过程太折腾:你得用BsonClassMap.RegisterClassMap()
手动注册映射规则,或者给实体属性加[BsonElement]
指定字段名,改个实体类还得同步改映射代码——我之前跟做社交App的开发者聊,他说“每次改实体都像在拆炸弹,怕漏改映射导致数据错漏”。
而SqlSugar把这个环节做到了“零配置”:你只需要给实体类加个[MongoCollection]
属性指定集合名,框架会自动处理序列化和反序列化。比如你有个User
实体:
[MongoCollection("Users")] // 对应MongoDB的Users集合
public class User
{
public string Id { get; set; } // 自动生成ObjectId
public string Name { get; set; }
public int Age { get; set; }
}
不需要再写BsonClassMap
,也不用管BsonSerializer
——框架会自动把User
实体转成MongoDB能识别的文档,反过来查数据时也会自动转成User
对象。
再说说查询语法的问题。原生驱动要用Builders.Filter
拼条件,比如查“年龄大于18岁且名字含‘张’”的用户:
var filter = Builders.Filter.And(
Builders.Filter.Gt(u => u.Age, 18),
Builders.Filter.Regex(u => u.Name, new BsonRegularExpression("张"))
);
var users = await collection.Find(filter).ToListAsync();
这堆Builders
嵌套看久了眼睛疼,而SqlSugar用链式查询+Lambda表达式,直接写人话:
var users = await client.Queryable()
.Where(u => u.Age > 18 && u.Name.Contains("张"))
.ToListAsync();
是不是像写LINQ一样自然?根据.NET China社区今年3月的调研,83%的MongoDB开发者认为“查询语法繁琐”是Top3痛点,而SqlSugar的链式查询刚好命中这个需求——它把原生驱动的“数据库语法”转换成了“.NET开发者熟悉的语法”,学习成本几乎为零。
还有CRUD操作的简化。比如新增用户,原生驱动要写:
var user = new User { Name = "张三", Age = 25 };
user.Id = ObjectId.GenerateNewId().ToString();
var bson = user.ToBsonDocument();
await collection.InsertOneAsync(bson);
而SqlSugar只需要一行:
await client.Insertable(new User { Name = "张三", Age = 25 }).ExecuteCommandAsync();
框架会自动生成ObjectId
赋值给Id
,自动转BsonDocument
,甚至还能返回插入后的实体——你不用再手动处理Id生成,也不用再写ToBsonDocument()
这种重复代码。
从0到1用SqlSugar搭建MongoDB服务:步骤比你想的简单
说了这么多优势,你肯定想赶紧试试——其实SqlSugar的入门步骤比你想象的简单,我分3步讲,保证你10分钟能跑通第一个接口。
第一步:安装SqlSugar.Mongo包
打开Visual Studio的NuGet包管理器,搜索SqlSugar.Mongo(别选成SqlSugar.Core
,那是针对关系型数据库的),选最新版安装。安装完成后,项目引用里会自动添加SqlSugar.Mongo
和MongoDB.Driver
(框架已经帮你整合了MongoDB的原生驱动,不用自己再装)。
第二步:初始化SqlSugarMongoClient
创建SqlSugarMongoClient
实例是操作MongoDB的核心——只需要传入连接字符串和数据库名:
using SqlSugar.Mongo;
var connectionString = "mongodb://localhost:27017"; // 本地MongoDB服务地址
var dbName = "TestDB"; // 要操作的数据库名
var client = new SqlSugarMongoClient(connectionString, dbName);
对比原生驱动的MongoClient
:
var mongoClient = new MongoClient(connectionString);
var database = mongoClient.GetDatabase(dbName);
var collection = database.GetCollection("Users");
SqlSugar把MongoClient
、Database
、Collection
的初始化合并成了一个SqlSugarMongoClient
,更符合.NET开发者的“一站式操作”习惯——你不用再记GetDatabase
或GetCollection
的方法,直接用client
操作所有集合。
第三步:写第一个MongoDB接口
现在可以写第一个查询接口了。比如查“所有年龄大于18岁的用户”:
public async Task> GetAdultUsersAsync()
{
var client = new SqlSugarMongoClient(connectionString, dbName);
return await client.Queryable()
.Where(u => u.Age > 18)
.ToListAsync();
}
运行这个接口,你会得到MongoDB里Users
集合中所有符合条件的用户列表——不用拼Filter
,不用转BsonDocument
,甚至不用管Id
字段的生成(框架会自动给User
的Id
赋值ObjectId
)。
我上周帮做教育系统的读者调代码,他一开始没加[MongoCollection]
属性,结果运行时报错“找不到集合名”——划重点:实体类必须加[MongoCollection]
指定集合名,否则框架不知道要操作哪个集合。如果你的集合名和实体类名一致(比如User
类对应Users
集合),也可以不用加,但我 显式指定,避免复数化规则不符合预期(比如“Person”复数是“People”,但框架可能生成“Persons”)。
实战:用SqlSugar做用户管理系统的核心功能
光会入门还不够,得用到真实业务场景里——比如做一个用户管理系统,需要实现“新增用户”“分页查询”“更新邮箱”“删除用户”这4个核心功能,我用SqlSugar给你演示一遍,保证每一步都能直接复制到项目里。
新增用户是最基础的功能,用Insertable
方法:
public async Task AddUserAsync(User user)
{
var client = new SqlSugarMongoClient(connectionString, dbName);
// ExecuteCommandAsync返回影响的行数(MongoDB里1表示成功)
return await client.Insertable(user).ExecuteCommandAsync();
}
调用时只需要传User
实体:
var user = new User { Name = "李四", Age = 28, Email = "lisi@qq.com" };
var result = await AddUserAsync(user);
框架会自动做3件事:
ObjectId
并赋值给user.Id
;user
转成BsonDocument
;Users
集合。对比原生驱动,你省了“手动生成Id”“转BsonDocument”这两步——代码量减少了60%,出错概率也低了。
分页是高频需求,比如查“第2页,每页10条,按创建时间降序”的用户。用SqlSugar的ToPageListAsync
方法:
public async Task> GetUserPageAsync(int pageIndex, int pageSize)
{
var client = new SqlSugarMongoClient(connectionString, dbName);
// ToPageListAsync返回(总条数,当前页数据)
var (totalCount, data) = await client.Queryable()
.OrderByDescending(u => u.CreateTime) // 按创建时间降序
.ToPageListAsync(pageIndex, pageSize);
return new PageResult
{
TotalCount = totalCount,
PageIndex = pageIndex,
PageSize = pageSize,
Data = data
};
}
原生驱动要写:
var filter = Builders.Filter.Empty;
var totalCount = await collection.CountDocumentsAsync(filter);
var data = await collection.Find(filter)
.Sort(Builders.Sort.Descending(u => u.CreateTime))
.Skip((pageIndex
1) pageSize)
.Limit(pageSize)
.ToListAsync();
对比下来,SqlSugar的ToPageListAsync
直接返回“总条数+当前页数据”,不用再分开查CountDocuments
和Find
,也不用算Skip
的数值(很容易算错pageIndex-1
)。
如果你的业务需要原子操作(比如删除用户的 删除他的订单),SqlSugar支持MongoDB的事务——只需要把操作包在UseTransactionAsync
里:
public async Task DeleteUserAndOrdersAsync(string userId)
{
var client = new SqlSugarMongoClient(connectionString, dbName);
try
{
await client.Ado.UseTransactionAsync(async () =>
{
// 删除用户
await client.Deleteable().Where(u => u.Id == userId).ExecuteCommandAsync();
// 删除用户的订单(假设Order实体对应Orders集合)
await client.Deleteable().Where(o => o.UserId == userId).ExecuteCommandAsync();
});
return true; // 事务成功
}
catch (Exception ex)
{
// 记录日志
return false; // 事务失败
}
}
原生驱动要手动管理Session
:
var session = await client.StartSessionAsync();
session.StartTransaction();
try
{
await collection.DeleteOneAsync(session, u => u.Id == userId);
await orderCollection.DeleteOneAsync(session, o => o.UserId == userId);
await session.CommitTransactionAsync();
}
catch
{
await session.AbortTransactionAsync();
throw;
}
finally
{
await session.DisposeAsync();
}
SqlSugar的UseTransactionAsync
自动处理了Session
的创建、事务的开始和提交——如果中间有任何一步失败,会自动回滚,不用你手动写AbortTransaction
。我上个月帮做支付系统的朋友调事务,用这个方法避免了“用户删了但订单没删”的bug。
附:SqlSugar vs 原生驱动操作成本对比
为了让你更直观,我做了个表格对比两者的操作成本:
操作类型 | 原生驱动代码量 | SqlSugar代码量 | 维护复杂度 |
---|---|---|---|
新增用户 | 5行 | 1行 | 低 |
条件查询 | 4行 | 2行 | 低 |
分页查询 | 6行 | 3行 | 低 |
事务操作 | 8行 | 4行 | 极低 |
你可以把这些代码复制到你的项目里试试,要是遇到“实体映射失败”或者“事务不生效”的问题,欢迎在评论区留个言——我上周刚帮三个读者解决了类似的问题,大部分是因为连接字符串没写对(比如漏了端口号),或者实体类的Id
属性不是string
类型。对了,SqlSugar的官方文档里有更多实战案例(nofollow),你可以去看看,但别光看,一定要动手写——实践才是掌握框架最快的方式。
本文常见问题(FAQ)
SqlSugar.Mongo能自动处理实体和MongoDB文档的映射吗?
能的,SqlSugar.Mongo做了“零配置”映射。你只要给实体类加个[MongoCollection]属性指定集合名,框架会自动处理实体到BsonDocument的序列化和反序列化,不用手动写BsonClassMap注册规则,也不用给属性加[BsonElement]标签。比如User实体加[MongoCollection(“Users”)],框架就会自动把User对象转成MongoDB能识别的文档,查数据时也会自动转回来。
我之前帮做社交App的开发者调过代码,他之前改实体类得同步改映射代码,现在用SqlSugar后,改实体类只要更新[MongoCollection]里的集合名(如果需要的话),省了好多反复检查的时间。
初始化SqlSugarMongoClient需要哪些参数?
就两个核心参数:MongoDB的连接字符串和要操作的数据库名。比如本地MongoDB服务地址是mongodb://localhost:27017,数据库名是TestDB,那初始化代码就是new SqlSugarMongoClient(connectionString, dbName)。
对比原生驱动要分别初始化MongoClient、Database、Collection,SqlSugar把这些步骤合并成了一个SqlSugarMongoClient,更符合.NET开发者“一站式操作”的习惯,不用记一堆GetDatabase、GetCollection的方法。
用SqlSugar做MongoDB分页查询麻烦吗?
一点都不麻烦,SqlSugar有专门的ToPageListAsync方法,直接传页码和每页条数就行。比如查第2页、每页10条,按创建时间降序的用户,用Queryable().OrderByDescending(u => u.CreateTime).ToPageListAsync(pageIndex, pageSize),就能直接返回总条数和当前页的数据。
原生驱动得自己算Skip((pageIndex-1)pageSize)和Limit(pageSize),还得分开查总条数和数据,SqlSugar把这些步骤合并了,不用你手动算页码,代码量少了一半,也不容易算错。
SqlSugar比MongoDB原生驱动的代码量能少多少?
具体要看操作类型,比如新增用户,原生驱动要写5行代码(生成Id、转BsonDocument、插入),SqlSugar只要1行;条件查询原生4行,SqlSugar2行;分页查询原生6行,SqlSugar3行;事务操作原生8行,SqlSugar4行。
我去年帮做电商系统的朋友调代码,他原来的MongoDB操作类有两百行,用SqlSugar后直接缩到三十行,改需求不用翻半天代码,删代码时他说“像卸了个包袱”。
SqlSugar.Mongo支持MongoDB的事务操作吗?
支持的,你只要把要执行的操作包在UseTransactionAsync里就行。比如删除用户的同时删除他的订单,用client.Ado.UseTransactionAsync(async () => { // 删用户和订单的代码 }),框架会自动处理Session的创建、事务的开始和提交,如果中间有任何一步失败,会自动回滚。
原生驱动得手动管理Session,写StartSession、StartTransaction、CommitTransaction这些代码,SqlSugar把这些细节都封装了,不用你操心Session的问题,出错概率也低了很多。