MongoDB .Net Driver:多态更新未遵循驼峰命名约定
MongoDB .NET Driver派生类属性不遵循驼峰命名约定的解决方法
我正在使用2.19.1版本的.NET Driver,以抽象基类作为文档类型,并配置了CamelCaseElementNameConvention约定:
ConventionRegistry.Register( CamelCaseName, new ConventionPack { new CamelCaseElementNameConvention() }, t => true);
基类属性的驼峰命名可正常生效,但当尝试更新文档的派生类属性时,属性名却以帕斯卡命名序列化。我的更新方法代码如下:
public async Task UpdateOneAsync<C>(Expression<Func<T, bool>> filter, string field, C obj) { await _mongoCollection.UpdateOneAsync(filter, Builders<T>.Update.Set(field, obj)); }
其中field字符串为帕斯卡命名,手动修正大小写后可正常运行,但我希望该约定能自动处理,请问如何让派生文档类的属性自动遵循该约定?
解决方案
方案1:用表达式获取字段名(推荐)
直接传字符串field时,Driver不会自动应用命名约定,改用属性表达式获取字段名,能自动适配约定规则,同时确保派生类序列化生效:
public async Task UpdateOneAsync<C>(Expression<Func<T, bool>> filter, Expression<Func<T, C>> fieldExpression, C obj) { // 通过表达式获取对应数据库字段名(自动应用驼峰约定) var fieldName = _mongoCollection.DocumentSerializer .GetMemberMap(fieldExpression) .ElementName; await _mongoCollection.UpdateOneAsync(filter, Builders<T>.Update.Set(fieldName, obj)); }
调用时直接传入属性表达式(例如x => x.MyDerivedProperty)即可,无需手动处理大小写。
方案2:适配字符串字段名的场景
如果必须保留字符串传参的方式,需要手动转换字段名并确保派生类使用约定序列化:
public async Task UpdateOneAsync<C>(Expression<Func<T, bool>> filter, string pascalFieldName, C obj) { // 将帕斯卡命名的属性名转换为驼峰字段名 var memberMap = _mongoCollection.DocumentSerializer .GetTypeMap() .GetMemberMap(pascalFieldName); var camelCaseFieldName = memberMap?.ElementName ?? pascalFieldName; // 使用全局配置的序列化器处理派生类对象,确保属性遵循驼峰约定 var serializer = BsonSerializer.LookupSerializer<C>(); var bsonObj = serializer.Serialize(obj); await _mongoCollection.UpdateOneAsync(filter, Builders<T>.Update.Set(camelCaseFieldName, bsonObj)); }
额外注意事项
- 检查派生类是否存在
[BsonElement]这类硬编码字段名的属性,该属性会覆盖全局约定。 - 若手动配置了
BsonClassMap,需确保派生类的配置继承了基类的命名约定规则。
内容的提问来源于stack exchange,提问作者tmaurst
相关产品推荐
相关产品推荐

