从MongoDB读取无类型数据遇未知鉴别器值错误,如何忽略鉴别器?
这个问题我之前也遇到过,本质是MongoDB C#驱动对_t鉴别器的默认处理逻辑和你的无类型读取需求冲突了。驱动看到_t字段就会尝试找到对应的.NET类型来反序列化,但你要么没定义这个类型,要么就是想直接以原始结构查看日志,不需要这个自动映射。给你几个实用的解决方案:
方案1:用BsonDocument读取并直接转为JSON(最适合日志查看场景)
因为你的核心需求是无类型展示日志,完全不需要把MongoDB文档反序列化成.NET对象,直接用BsonDocument读取,再转成JSON字符串传给前端是最直接的方式,能彻底避开鉴别器问题。修改代码如下:
// 获取BsonDocument类型的集合 var _collection = MongoDbFactory.GetDatabase(_connectionString).GetCollection<BsonDocument>(_collectionName); var logDocuments = _collection.Find(filter).ToList(); // 使用MongoDB自带的序列化工具转成标准JSON,避免第三方序列化器的兼容性问题 var logJsonList = logDocuments.Select(doc => doc.ToJson(new JsonWriterSettings { Indent = true, // 可选,格式化JSON方便前端查看 OutputMode = JsonOutputMode.Strict // 输出符合标准的JSON格式 })).ToList();
你之前用BsonDocument报错,大概率是误用了普通JSON序列化器(比如Newtonsoft.Json)来处理BsonDocument,换成MongoDB原生的ToJson方法就能完美解决。
方案2:配置序列化设置忽略鉴别器(如果需要反序列化为.NET对象)
如果你确实需要把日志反序列化为.NET对象做后端处理,可以给驱动配置序列化规则,让它忽略鉴别器字段:
// 创建自定义序列化设置:忽略鉴别器,同时忽略未知字段 var serializerSettings = new BsonSerializerSettings { DiscriminatorHandling = DiscriminatorHandling.Ignore, IgnoreExtraElements = true }; var _collection = MongoDbFactory.GetDatabase(_connectionString).GetCollection<object>(_collectionName); // 读取文档并按自定义规则反序列化 var logs = _collection.Find(filter) .ToList() .Select(doc => BsonSerializer.Deserialize<object>(doc.ToBson(), serializerSettings)) .ToList();
这个设置会告诉驱动不要解析_t字段,直接把整个文档当作无类型对象处理,不会再抛出"Unknown discriminator value"错误。
方案3:自定义日志模型类(最可控的结构化处理方式)
如果需要更结构化地处理日志,同时保留动态内容的灵活性,可以定义一个日志模型类,把包含动态数据的字段(比如routedata)声明为BsonDocument类型:
public class MongoLogEntry { [BsonId] public ObjectId Id { get; set; } public DateTime Timestamp { get; set; } public string Level { get; set; } public string Thread { get; set; } public string Logger { get; set; } public string Message { get; set; } public BsonDocument ExceptionData { get; set; } public BsonDocument UserData { get; set; } public BsonDocument RouteData { get; set; } // 动态路由数据用BsonDocument存储 public BsonDocument Data { get; set; } }
然后用这个模型类读取日志:
var _collection = MongoDbFactory.GetDatabase(_connectionString).GetCollection<MongoLogEntry>(_collectionName); var logs = _collection.Find(filter).ToList();
这种方式既保留了日志核心字段的结构化,又让动态内容以原始形式存在,不会触发驱动的鉴别器解析逻辑。
内容的提问来源于stack exchange,提问作者erik_nw
相关产品推荐
相关产品推荐

