我正在使用最新版本的 NodaTime 和 Mongo DB Official Driver 。我有一个简单的 POCO 类,它在一些属性中使用 NodaTime 的 ZonedDateTime
作为 .NET DateTime 的替代品。
public class MyPOCO
{
[BsonId]
[Key]
public ObjectId SomeId { get; set; }
public string SomeProperty { get; set; }
public ZonedDateTime SomeDateTime { get; set; }
}
我可以轻松地将模型放入集合中,但是当我尝试读取查询的模型时,我得到以下
MongoDB.Bson.BsonSerializationException
:解决/解决此问题的好方法或最佳做法是什么?
更新
将我的 solution 发布到问题后,我面临一个可能的新问题...当我查询集合并在查询中使用 DateTime 时,例如
where SomeDateTime < now' (where
now is a variable I create from system time) it seems that each document must be deserialized using my
ZonedDateTimeSerializer` ,然后可以评估 where 子句。这看起来是一个很大的性能问题,不是吗?我真的必须考虑再次回到 BCL DateTime,即使它很痛苦。更新 2
我使用
ZonedDateTimeSerializer
接受我的解决方案,但我对 NodaTime 与 MongoDB 的结合感到不舒服,而两者都是很好的个人解决方案。但是,如果没有大量操作,它们目前无法很好地协同工作。 最佳答案
没关系,经过大量阅读和实验,终于找到了。我编写了一个自定义 BsonBaseSerializer
实现来处理 ZonedDateTime
。
这是我的 ZonedDateTimeSerializer
的代码:
/// <summary>
/// Serializer for the Noda
/// </summary>
public class ZonedDateTimeSerializer : BsonBaseSerializer
{
private static ZonedDateTimeSerializer __instance = new ZonedDateTimeSerializer();
/// <summary>
/// Initializes a new instance of the ZonedDateTimeSerializer class.
/// </summary>
public ZonedDateTimeSerializer()
{
}
/// <summary>
/// Gets an instance of the ZonedDateTimeSerializer class.
/// </summary>
public static ZonedDateTimeSerializer Instance
{
get { return __instance; }
}
/// <summary>
/// Deserializes an object from a BsonReader.
/// </summary>
/// <param name="bsonReader">The BsonReader.</param>
/// <param name="nominalType">The nominal type of the object.</param>
/// <param name="actualType">The actual type of the object.</param>
/// <param name="options">The serialization options.</param>
/// <returns>
/// An object.
/// </returns>
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
VerifyTypes(nominalType, actualType, typeof(ZonedDateTime));
var bsonType = bsonReader.GetCurrentBsonType();
if (bsonType == BsonType.DateTime)
{
var millisecondsSinceEpoch = bsonReader.ReadDateTime();
return new Instant(millisecondsSinceEpoch).InUtc();
}
throw new InvalidOperationException(string.Format("Cannot deserialize ZonedDateTime from BsonType {0}.", bsonType));
}
/// <summary>
/// Serializes an object to a BsonWriter.
/// </summary>
/// <param name="bsonWriter">The BsonWriter.</param>
/// <param name="nominalType">The nominal type.</param>
/// <param name="value">The object.</param>
/// <param name="options">The serialization options.</param>
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
if (value == null)
throw new ArgumentNullException("value");
var ZonedDateTime = (ZonedDateTime)value;
bsonWriter.WriteDateTime(ZonedDateTime.ToInstant().Ticks);
}
}
不要忘记注册序列化程序。我无法找出如何按类型注册序列化程序,但您可以按类型注册它,如下所示:
BsonClassMap.RegisterClassMap<MyPOCO>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(a => a.SomeDateTime).SetSerializer(ZonedDateTimeSerializer.Instance);
});
希望这可以帮助。
关于c# - NodaTime 与 MongoDB : Value class NodaTime. ZonedDateTime 不能反序列化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17882795/