SmartDapper.Repository 是基于 SmartDapper 的 Repository + UnitOfWork 封装,提供一致的 CRUD / 分页 API,并统一事务边界(支持自动提交/回滚与嵌套事务复用),用于组织数据访问层代码。
功能特性
- 泛型仓储 :
IRepository<T>+Repository<T>(内置常用 CRUD/分页) - 工作单元 :
IUnitOfWork+UnitOfWork(统一连接与事务) - 事务作用域 :
ITransactionScope+TransactionScope(未Complete()自动回滚;支持复用外层事务) - 事务快捷封装 :
ExecuteInTransaction*扩展方法,一行包裹事务边界
安装
bash
dotnet add package SmartDapper.Repository
快速开始(ASP.NET Core)
方式 A:只使用 Repository + UnitOfWork(不依赖中间件)
在 Program.cs 统一注册 IDbConnection / IUnitOfWork / IRepository<>(推荐):
csharp
using System.Data;
using Microsoft.Data.SqlClient;
using SmartDapper.Repository.Extensions;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("Default")!;
builder.Services.AddSmartDapperRepository(
connectionString,
cs => new SqlConnection(cs));
提示:如果不是 SQL Server,请自行替换连接类型,或实现你自己的
connectionFactory。
方式 A2(推荐):配合 AddSmartDapperConnections(多连接工厂)
如果你已经使用 SmartDapper 的多连接工厂(AddSmartDapperConnections),可以直接让 Repository 复用工厂配置:
csharp
using Microsoft.Data.SqlClient;
using SmartDapper.Extensions;
using SmartDapper.Repository.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSmartDapperConnections(o =>
{
o.Add("Main", builder.Configuration.GetConnectionString("Main")!, cs => new SqlConnection(cs));
o.DefaultKey = "Main";
});
// 默认连接(CreateDefault)
builder.Services.AddSmartDapperRepository();
// 或指定 key(Create("Main"))
// builder.Services.AddSmartDapperRepository("Main");
方式 B:使用 SmartDapper.Middleware(包含 DI 注册 + 声明式事务)
如果你的项目是 Web API,并希望通过 [UnitOfWork] 自动开启事务,推荐直接用中间件包:
csharp
using Microsoft.Data.SqlClient;
using SmartDapper.Middleware.Extensions;
using SmartDapper.Repository.Extensions;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("Default")!;
// 注册仓储 + 工作单元
builder.Services.AddSmartDapperRepository(connectionString, cs => new SqlConnection(cs));
var app = builder.Build();
// 注册工作单元中间件(可选:配合 [UnitOfWork])
app.UseSmartDapperUnitOfWork();
app.MapControllers();
app.Run();
基础用法
csharp
public class CustomerService
{
private readonly IRepository<Customer> _repo;
public CustomerService(IRepository<Customer> repo)
{
_repo = repo;
}
public async Task<long> CreateAsync(Customer customer)
{
// 插入并返回自增 ID(如果你的实体/表是自增主键)
return await _repo.InsertAndGetIdAsync(customer);
}
public Task<List<Customer>> ListAsync()
=> _repo.GetAllListAsync();
}
事务用法(推荐)
推荐 1:扩展方法 ExecuteInTransaction*(最简洁)
csharp
using SmartDapper.Repository.Extensions;
await _unitOfWork.ExecuteInTransactionAsync(async () =>
{
await _customerRepository.InsertAsync(customer);
await _orderRepository.InsertAsync(order);
});
推荐 2:CreateTransactionScope(可控且支持嵌套复用)
csharp
await using var scope = _unitOfWork.CreateTransactionScope();
try
{
await _customerRepository.InsertAsync(customer);
await _orderRepository.InsertAsync(order);
await scope.CompleteAsync(); // 提交
}
catch
{
// 未 Complete 时:DisposeAsync 自动回滚
throw;
}
嵌套说明:如果外层已存在事务,
TransactionScope会自动复用外层事务,不会重复开启新事务。
不推荐:直接 BeginTransaction(需要你手动 Commit/Rollback)
如果你确实需要"完全手动控制提交/回滚",可以使用 BeginTransaction/Commit/Rollback(请务必显式提交/回滚,避免长事务)。
生命周期与资源释放(重要)
- 典型 Web 场景 :
IUnitOfWork/IDbConnection建议按Scoped注册(每个请求一个实例)。 - 请求结束释放 :DI 容器会调用
Dispose/DisposeAsync;若发现"未结束事务",UnitOfWork会进行防御性回滚并释放连接资源。 - 后台任务/非 HTTP 场景 :请手动创建 DI Scope,并在 scope 生命周期内使用同一个
IUnitOfWork。