C#使用MongoDB.Driver时无法访问MongoCollection类及Save方法
问题根因
MongoDB官方C#驱动从2.0版本开始已经完全移除了1.x版本中存在的MongoCollection类以及对应的Save()方法,你查阅到的提到Save()的文档均为旧版驱动的遗留内容,新版驱动的IMongoCollection接口本身没有内置Save()实现,这就是你IDE报错、找不到对应定义的核心原因。
如果一定要使用原生MongoCollection类和Save()方法,只能将C#驱动版本回退到1.x系列,但该版本已经停止维护多年,兼容性和性能都较差,不推荐使用。
通用Save()扩展方法实现方案
你可以自行给IMongoCollection编写扩展方法模拟旧版Save()的逻辑:自动判断文档_id是否为默认值,是则走插入逻辑,否则走基于_id的全量替换逻辑,完全符合你封装通用IMongoRepository、无需额外参数即可完成新增/更新的需求,实现代码如下:
using MongoDB.Driver; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; using System.Reflection; public static class MongoCollectionExtensions { /// <summary> /// 模拟旧版Save方法,自动判断新增或更新 /// </summary> public static void Save<TDocument>(this IMongoCollection<TDocument> collection, TDocument document) where TDocument : class { // 查找文档的Id字段,优先找标记了[BsonId]的属性,其次找名为Id的属性 PropertyInfo idProperty = typeof(TDocument).GetProperties() .FirstOrDefault(p => p.GetCustomAttributes(typeof(BsonIdAttribute), true).Any()) ?? typeof(TDocument).GetProperty("Id"); if (idProperty == null) { throw new InvalidOperationException("目标文档未定义Id字段,请添加[BsonId]标记或命名属性为Id"); } object idValue = idProperty.GetValue(document); // 判断Id是否为默认值(覆盖常用Id类型的默认情况) bool idIsDefault = idValue switch { null => true, ObjectId objectId => objectId == ObjectId.Empty, string strId => string.IsNullOrWhiteSpace(strId), Guid guidId => guidId == Guid.Empty, _ => EqualityComparer<object>.Default.Equals(idValue, Activator.CreateInstance(idProperty.PropertyType)) }; if (idIsDefault) { collection.InsertOne(document); } else { FilterDefinition<TDocument> idFilter = Builders<TDocument>.Filter.Eq("_id", idValue); collection.ReplaceOne(idFilter, document, new ReplaceOptions { IsUpsert = true }); } } /// <summary> /// 异步版本Save方法 /// </summary> public static async Task SaveAsync<TDocument>(this IMongoCollection<TDocument> collection, TDocument document, CancellationToken cancellationToken = default) where TDocument : class { PropertyInfo idProperty = typeof(TDocument).GetProperties() .FirstOrDefault(p => p.GetCustomAttributes(typeof(BsonIdAttribute), true).Any()) ?? typeof(TDocument).GetProperty("Id"); if (idProperty == null) { throw new InvalidOperationException("目标文档未定义Id字段,请添加[BsonId]标记或命名属性为Id"); } object idValue = idProperty.GetValue(document); bool idIsDefault = idValue switch { null => true, ObjectId objectId => objectId == ObjectId.Empty, string strId => string.IsNullOrWhiteSpace(strId), Guid guidId => guidId == Guid.Empty, _ => EqualityComparer<object>.Default.Equals(idValue, Activator.CreateInstance(idProperty.PropertyType)) }; if (idIsDefault) { await collection.InsertOneAsync(document, null, cancellationToken); } else { FilterDefinition<TDocument> idFilter = Builders<TDocument>.Filter.Eq("_id", idValue); await collection.ReplaceOneAsync(idFilter, document, new ReplaceOptions { IsUpsert = true }, cancellationToken); } } }
使用方式
在项目中引入上述扩展类后,即可直接通过IMongoCollection实例调用Save()或SaveAsync()方法,无需额外传参即可完成基于_id的新增/更新操作。
你遇到的IDE报错参考如下:
内容的提问来源于stack exchange,提问作者Musab Marzouque
相关产品推荐
相关产品推荐

