使用MongoDB Driver插入种子数据后读取到类默认值问题排查
问题描述
封装功能时,验证MongoDB集合是否存入种子数据,但读取后得到的是类的默认值(null、0等)。
类A定义:
public sealed record A { public int ID { get; } public string StartId { get; } public string EndId { get; } public A(int id, string startId, string endId){ Id = id; StartId = startId; EndId = endId; } }
种子数据及数据库创建代码:
private readonly A[] seed = new []{ new A(1, "n1", "100"), new A(2, "n2", "90") }; private IMongoDatabase MakeDatabase<T>(string dbName, string? collectionName, IEnumerable<T>? seed) { var client = new MongoClient(MongoRunner.Run().ConnectionString); var database = client.GetDatabase(dbName); if (collectionName != null) { database.CreateCollection(collectionName); database.GetCollection<T>(collectionName).InsertMany(seed); // 检查集合是否有正确的种子数据 var collection = database.GetCollection<T>(collectionName); foreach (var x in collection.Aggregate().ToList()) { Console.WriteLine(x); Console.Write("sfdfasd"); } } return database; }
调用上述方法插入种子后,查询输出类默认值,请问遗漏了什么?
问题原因及解决方法
字段大小写不匹配:类A中定义的属性是
ID(大写D),但构造函数里赋值的是Id(小写d)。这会导致构造函数无法正确初始化ID属性,插入到MongoDB时该字段值为默认的0;同时MongoDB默认的序列化/反序列化会区分大小写,读取时无法映射到正确的属性,最终返回默认值。
解决:把构造函数里的Id = id;改成ID = id;,保持属性名和构造函数赋值的一致性。MongoDB序列化配置缺失:对于C# record类型,MongoDB驱动需要正确的序列化配置才能识别不可变属性。如果没有配置,驱动可能无法正确将文档映射到record实例,导致返回默认值。
解决:在record类上添加[BsonConstructor]特性,指定驱动使用正确的构造函数:public sealed record A { public int ID { get; } public string StartId { get; } public string EndId { get; } [BsonConstructor] public A(int id, string startId, string endId){ ID = id; StartId = startId; EndId = endId; } }也可以全局配置驱动使用构造函数映射:
var conventionPack = new ConventionPack { new IgnoreExtraElementsConvention(true), new ConstructorConvention() }; ConventionRegistry.Register("CustomConventions", conventionPack, t => true); var client = new MongoClient(MongoRunner.Run().ConnectionString);写入确认机制缺失:在测试环境的内存Mongo实例中,同步插入可能存在微小延迟,导致立即查询时读取不到最新数据。
解决:插入时设置写入关注级别,确保写入完成后再查询:var collection = database.GetCollection<T>(collectionName); var options = new InsertManyOptions { WriteConcern = WriteConcern.WMajority }; collection.InsertMany(seed, options);
内容的提问来源于stack exchange,提问作者so_
相关产品推荐
相关产品推荐

