Dpz.Core.MongodbAccess
一个基于 MongoDB.Driver 数据访问层封装库,实现了完整的仓储模式(Repository Pattern)和工作单元模式(Unit of Work Pattern)。
📋 主要特性
- ✅ 仓储模式(Repository Pattern):提供统一的数据访问接口,简化 CRUD 操作
- ✅ 工作单元模式(Unit of Work Pattern):完整支持事务管理,确保数据一致性
- ✅ 全异步操作:所有 CRUD 操作均支持异步,提升性能
- ✅ 表达式树查询:支持 LINQ 表达式查询,类型安全
- ✅ 依赖注入友好:原生支持 .NET 依赖注入容器
- ✅ 性能优化:使用表达式树缓存和并发字典提升性能
- ✅ 灵活的集合命名:支持自定义集合名称
🔧 技术栈
- .NET 10.0
- MongoDB.Driver 3.5.2
- MongoDB.Analyzer 2.0.0
📦 快速开始
配置连接字符串
在 appsettings.json 中配置 MongoDB 连接字符串:
{
"ConnectionStrings": {
"mongodb": "mongodb://localhost:27017/YourDatabase"
}
}
依赖注入配置
// 注册仓储服务(推荐使用 Transient 生命周期)
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
// 注册工作单元服务(必须使用 Transient 生命周期)
services.AddTransient<IUnitOfWork, UnitOfWork>();
💡 使用示例
1. 基础 Repository 使用
定义实体
public class UserEntity : BaseEntity
{
public string Name { get; set; } = "";
public string Email { get; set; } = "";
public int Age { get; set; }
}
基本 CRUD 操作
// 通过依赖注入获取 Repository
public class UserService
{
private readonly IRepository<UserEntity> _userRepository;
public UserService(IRepository<UserEntity> userRepository)
{
_userRepository = userRepository;
}
// 插入数据
public async Task CreateUserAsync(UserEntity user)
{
await _userRepository.InsertAsync(user);
}
// 查询数据
public async Task<List<UserEntity>> GetUsersAsync()
{
return await _userRepository.SearchFor(x => x.Age > 18).ToListAsync();
}
// 更新数据
public async Task UpdateUserAsync(UserEntity user)
{
await _userRepository.UpdateAsync(user);
}
// 删除数据
public async Task DeleteUserAsync(object userId)
{
await _userRepository.DeleteAsync(userId);
}
}
2. 工作单元(Unit of Work)使用
工作单元模式用于管理多个仓储的事务,确保多个操作的原子性。
基本事务操作
public class OrderService
{
private readonly IUnitOfWork _unitOfWork;
public OrderService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public async Task CreateOrderAsync()
{
// 获取多个仓储
var orderRepo = _unitOfWork.GetRepository<OrderEntity>();
var productRepo = _unitOfWork.GetRepository<ProductEntity>();
// 开始事务
_unitOfWork.Begin();
try
{
// 创建订单
var order = new OrderEntity { /* ... */ };
await orderRepo.InsertAsync(order);
// 更新库存
var updateDef = Builders<ProductEntity>.Update.Inc(x => x.Stock, -1);
await productRepo.UpdateAsync(x => x.Id == productId, updateDef);
// 提交事务
await _unitOfWork.CommitAsync();
}
catch (Exception)
{
// 回滚事务
await _unitOfWork.RollbackAsync();
throw;
}
}
}
完整的事务示例
public class UnitOfWorkTestEntity : BaseEntity
{
public string Value { get; set; } = "";
}
public class UnitOfWorkTestEntity2 : BaseEntity
{
public string Value { get; set; } = "";
}
// 使用工作单元进行事务操作
using var uow = serviceProvider.GetService<IUnitOfWork>();
// 获取仓储(同一类型的 Repository 在同一工作单元中是单例)
var repository1 = uow.GetRepository<UnitOfWorkTestEntity>();
var repository2 = uow.GetRepository<UnitOfWorkTestEntity2>();
// 开始事务
uow.Begin();
// 清空数据
await repository1.DeleteAsync(x => true);
await repository2.DeleteAsync(x => true);
// 插入新数据
var entity1 = new UnitOfWorkTestEntity { Value = Guid.NewGuid().ToString("N") };
await repository1.InsertAsync(entity1);
var entity2 = new UnitOfWorkTestEntity2 { Value = Guid.NewGuid().ToString("N") };
await repository2.InsertAsync(entity2);
// 提交事务
await uow.CommitAsync();
// ===== 测试事务回滚 =====
using var uow2 = serviceProvider.GetService<IUnitOfWork>();
var repository3 = uow2.GetRepository<UnitOfWorkTestEntity>();
var repository4 = uow2.GetRepository<UnitOfWorkTestEntity2>();
var guid1 = Guid.NewGuid().ToString("N");
var guid2 = Guid.NewGuid().ToString("N");
try
{
// 验证之前的数据已提交
var list1 = await repository3.SearchFor(x => true).ToListAsync();
Assert.IsNotNull(list1);
Assert.IsNotEmpty(list1);
// 开始新事务
uow2.Begin();
var entity3 = new UnitOfWorkTestEntity { Value = guid1 };
var entity4 = new UnitOfWorkTestEntity2 { Value = guid2 };
await repository3.InsertAsync(entity3);
await repository4.InsertAsync(entity4);
// 注意:MongoDB 在事务内可以查询到未提交的数据
var r1 = await repository3.SearchFor(x => x.Value == guid1).FirstOrDefaultAsync();
Assert.IsNotNull(r1);
// 模拟异常
throw new Exception("测试回滚");
}
catch (Exception)
{
// 回滚事务
await uow2.RollbackAsync();
}
// 验证回滚后数据不存在
var repo1 = new Repository<UnitOfWorkTestEntity>(connectionString);
var result1 = await repo1.SearchFor(x => x.Value == guid1).FirstOrDefaultAsync();
Assert.IsNull(result1); // 数据已回滚,应为 null
3. 高级查询
// LINQ 表达式查询
var users = await _userRepository
.SearchFor(x => x.Age > 18 && x.Name.StartsWith("Zhang"))
.ToListAsync();
// MongoDB FilterDefinition 查询
var filter = Builders<UserEntity>.Filter.And(
Builders<UserEntity>.Filter.Gt(x => x.Age, 18),
Builders<UserEntity>.Filter.Regex(x => x.Name, "^Zhang")
);
var result = await _userRepository.SearchFor(filter).ToListAsync();
// 异步流式查询(适合大数据量)
await foreach (var user in _userRepository.SearchForAsync(filter))
{
Console.WriteLine(user.Name);
}
4. 批量操作
// 批量插入
var users = new List<UserEntity>
{
new UserEntity { Name = "User1" },
new UserEntity { Name = "User2" },
new UserEntity { Name = "User3" }
};
await _userRepository.InsertAsync(users);
// 批量更新
var usersToUpdate = await _userRepository.SearchFor(x => x.Age > 18).ToListAsync();
foreach (var user in usersToUpdate)
{
user.Age += 1;
}
await _userRepository.UpdateAsync(usersToUpdate);
📚 核心接口说明
IRepository
提供完整的 CRUD 操作接口:
Task<T?> FindAsync(object id)- 根据 ID 查找实体Task InsertAsync(T entity)- 插入单个实体Task InsertAsync(IReadOnlyCollection<T> source)- 批量插入Task<DeleteResult> DeleteAsync(Expression<Func<T, bool>> filter)- 删除数据Task<UpdateResult> UpdateAsync(Expression<Func<T, bool>> predicate, UpdateDefinition<T> update)- 更新数据Task<ReplaceOneResult> UpdateAsync(T entity)- 替换实体IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)- LINQ 查询IAsyncEnumerable<T> SearchForAsync(FilterDefinition<T> filter)- 异步流式查询
IUnitOfWork
提供工作单元和事务管理:
void Begin()- 开始工作单元(启动事务)IRepository<T> GetRepository<T>()- 获取指定类型的仓储IRepository<T> GetRepository<T>(string collectionName)- 获取指定集合名称的仓储Task CommitAsync()- 提交事务Task RollbackAsync()- 回滚事务
⚠️ 注意事项
事务支持:MongoDB 单实例默认不支持事务,需要配置为副本集。参考:单实例事务解决方案
工作单元生命周期:
IUnitOfWork必须以 Transient 方式注入,确保每次使用都是新实例。实体要求:实体类必须继承
IBaseEntity接口,并包含Id属性或使用[BsonId]特性标记主键。事务内查询:MongoDB 在事务内可以查询到未提交的数据,这是正常行为。
性能优化:库内使用了表达式树缓存和并发字典优化性能,无需担心反射性能问题。
📖 更新日志
- 2019年12月9日:
UnitOfWork部分实现 - 2019年12月20日:
UnitOfWork大部分实现 - 当前版本:
UnitOfWork已完全实现,支持完整的事务管理
📄 许可证
本项目基于 MIT 许可证开源。
🔗 相关链接
- MongoDB 官方文档:https://www.mongodb.com/docs/drivers/csharp/
评论加载中...