如何在C#中通过MongoDb.Driver实现软删除全局过滤(无需EF)
在MongoDB Driver中实现软删除全局过滤(无需EntityFramework)
当然可以实现,以下是两种靠谱的方案,直接基于MongoDB Driver完成全局软删除过滤:
方案一:使用MongoDB Driver全局过滤器(推荐,Driver 2.10+支持)
通过配置MongoClient的全局过滤器,对所有实现ISoftDelete接口的实体自动添加过滤条件,无需在每次查询时手动处理。
实现步骤:
- 确保你的
ISoftDelete接口定义正确:
public interface ISoftDelete { bool IsDeleted { get; set; } }
- 在初始化
IMongoClient时,配置全局过滤器:
var settings = MongoClientSettings.FromConnectionString("你的MongoDB连接字符串"); settings.ClusterConfigurator = builder => { builder.Subscribe<CommandStartedEvent>(e => { // 只针对查询类命令添加过滤 if (e.CommandName == "find" || e.CommandName == "aggregate") { // 根据集合名获取对应的实体类型,你需要自己维护集合名与实体类型的映射逻辑 var entityType = GetEntityTypeByCollectionName(e.Command["find"].AsString); if (typeof(ISoftDelete).IsAssignableFrom(entityType)) { // 构造过滤条件:IsDeleted = false var filter = BsonDocument.Parse("{ IsDeleted: false }"); // 将过滤条件合并到原查询中 if (e.Command.Contains("filter")) { var existingFilter = e.Command["filter"].AsBsonDocument; e.Command["filter"] = new BsonDocument("$and", new BsonArray { existingFilter, filter }); } else { e.Command.Add("filter", filter); } } } }); }; var client = new MongoClient(settings);
方案二:自定义集合扩展方法(更灵活可控)
如果不想用全局过滤器,也可以封装一个扩展方法,每次获取集合时自动应用软删除过滤,统一管理查询逻辑。
实现代码:
public static class MongoCollectionExtensions { public static IMongoCollection<T> GetSoftDeleteCollection<T>(this IMongoDatabase database, string collectionName = null) { var collection = string.IsNullOrEmpty(collectionName) ? database.GetCollection<T>() : database.GetCollection<T>(collectionName); // 如果当前实体实现了ISoftDelete,返回带过滤的集合 if (typeof(ISoftDelete).IsAssignableFrom(typeof(T))) { var filter = Builders<T>.Filter.Eq(nameof(ISoftDelete.IsDeleted), false); return collection.WithFilter(filter); } return collection; } }
使用方式:
// 获取应用了软删除过滤的集合 var usersCollection = database.GetSoftDeleteCollection<User>(); // User实现了ISoftDelete // 普通查询自动排除已删除记录 var activeUsers = await usersCollection.Find(Builders<User>.Filter.Empty).ToListAsync(); // 如果需要查询已删除记录,手动构造包含IsDeleted=true的过滤器 var deletedUsers = await usersCollection.Find(Builders<User>.Filter.Eq(u => u.IsDeleted, true)).ToListAsync();
注意事项
- 执行批量更新/删除操作时,优先设置
IsDeleted字段标记软删除,而非真正删除文档。 - 全局过滤器会作用于所有符合条件的查询命令,包括聚合查询;若需包含已删除记录,可手动在查询中添加
IsDeleted: true的条件覆盖默认过滤。
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

