C#操作MongoDB聚合查询时如何反序列化DateTimeOffset类型
问题根源
MongoDB C# 驱动默认会将DateTimeOffset类型序列化为长度为2的数组存储:第一个元素存储UTC时间的Ticks值,第二个元素存储相对UTC的偏移分钟数,你在数据库里看到的[NumberLong(637919607231619015), 0]就是这个序列化结构。
聚合管道返回的是原始Bson文档,驱动不会自动做类型映射,因此theFirstItem["firstDate"]实际是BsonArray类型,直接调用ToUniversalTime()就会抛出你遇到的不支持异常。
可行解决方案
方法1:手动解析BsonArray取值
直接按照DateTimeOffset的存储结构从返回的Bson数组里读取值,手动构造对应类型即可:
var dateArray = theFirstItem["firstDate"].AsBsonArray; var utcTicks = dateArray[0].AsInt64; var offsetMinutes = dateArray[1].AsInt32; DateTimeOffset firstDate = new DateTimeOffset(utcTicks, TimeSpan.FromMinutes(offsetMinutes)); // 需要UTC时间直接取属性即可 DateTime firstDateUtc = firstDate.UtcDateTime;
方法2:定义强类型结果类,让驱动自动反序列化
给聚合返回的结果定义对应的实体类,聚合时直接指定返回类型,驱动会自动完成DateTimeOffset的类型转换,不需要手动处理Bson结构:
// 定义聚合返回结果的实体 class GroupResult { public int _id { get; set; } public DateTimeOffset firstDate { get; set; } } // 聚合时指定返回类型为GroupResult var theFirstItem = collection.Aggregate<TheThing>() .Group(new BsonDocument { // 这里修正了你原代码的笔误:分组字段要加$前缀,否则_id会固定为字符串"Number" { "_id", "$Number" }, { "firstDate", new BsonDocument { { "$first", "$Date" } } } }) .As<GroupResult>() .First(); // 直接读取属性即可,不需要额外转换 var firstDate = theFirstItem.firstDate;
额外提醒:你原代码Group阶段的_id配置少了
$前缀,写的是"Number",这会导致所有数据分到同一组,_id值为固定字符串"Number",和你贴出来的返回结果里"_id":1的预期不符,上面代码已经修正了这个问题。
内容的提问来源于stack exchange,提问作者Marcello
相关产品推荐
相关产品推荐

