MongoDB C#:DateTimeOffset到BsonType DateTime的序列化程式
目錄
目前不支援將DateTimeOffset序列化為MongoDB中的DateTime。該解決方案將向您展示它是如何工作的。
介紹
如果您需要DateTimeOffsets在模型中使用,並且希望將其儲存為BsonType DateTime,則會出現“ 'DateTime' is not a valid DateTimeOffset representation.”或“ Cannot deserialize a 'DateTimeOffset' from BsonType 'DateTime'.” 等錯誤
背景
我們在某些模型中使用DateTimeOffsets,因為我們有一個基於XML的匯入執行,其值包含DateTimeOffsets(XXXXXX +01:00)或類似值。雖然我們希望這些值能作為DateTime被儲存在MongoDB中。我們不太關心偏移資訊,儲存的UTC對我們來說很好。
您可以輕鬆在MongoDB中建立自己的DateTimeOffset序列化器並將其註冊為DateTimeOffset序列化器。我會告訴你如何處理。
使用程式碼
您可以檢視MongoDB C#客戶端的原始碼,看看如何構建DateTimeSerializer或DateTimeOffset序列化器,並調整其中的內容。最終的序列化程式可能如下所示:
public class DateTimeOffsetSupportingBsonDateTimeSerializer : StructSerializerBase<DateTimeOffset>, IRepresentationConfigurable<DateTimeOffsetSupportingBsonDateTimeSerializer> { private BsonType _representation; private string StringSerializationFormat = "YYYY-MM-ddTHH:mm:ss.FFFFFFK"; public DateTimeOffsetSupportingBsonDateTimeSerializer() : this(BsonType.DateTime) { } public DateTimeOffsetSupportingBsonDateTimeSerializer(BsonType representation) { switch (representation) { case BsonType.String: case BsonType.DateTime: break; default: throw new ArgumentException(string.Format("{0} is not a valid representation for {1}", representation, this.GetType().Name)); } _representation = representation; } public BsonType Representation => _representation; public override DateTimeOffset Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonReader = context.Reader; long ticks; TimeSpan offset; BsonType bsonType = bsonReader.GetCurrentBsonType(); switch (bsonType) { case BsonType.String: var stringValue = bsonReader.ReadString(); return DateTimeOffset.ParseExact (stringValue, StringSerializationFormat, DateTimeFormatInfo.InvariantInfo); case BsonType.DateTime: var dateTimeValue = bsonReader.ReadDateTime(); return DateTimeOffset.FromUnixTimeMilliseconds(dateTimeValue); default: throw CreateCannotDeserializeFromBsonTypeException(bsonType); } } public override void Serialize (BsonSerializationContext context, BsonSerializationArgs args, DateTimeOffset value) { var bsonWriter = context.Writer; switch (_representation) { case BsonType.String: bsonWriter.WriteString(value.ToString (StringSerializationFormat, DateTimeFormatInfo.InvariantInfo)); break; case BsonType.DateTime: bsonWriter.WriteDateTime(value.ToUnixTimeMilliseconds()); break; default: var message = string.Format("'{0}' is not a valid DateTimeOffset representation.", _representation); throw new BsonSerializationException(message); } } public DateTimeOffsetSupportingBsonDateTimeSerializer WithRepresentation(BsonType representation) { if(representation == _representation) { return this; } return new DateTimeOffsetSupportingBsonDateTimeSerializer(representation); } IBsonSerializer IRepresentationConfigurable.WithRepresentation(BsonType representation) { return WithRepresentation(representation); } protected Exception CreateCannotDeserializeFromBsonTypeException(BsonType bsonType) { var message = string.Format("Cannot deserialize a '{0}' from BsonType '{1}'.", BsonUtils.GetFriendlyTypeName(ValueType), bsonType); return new FormatException(message); } }
生成的序列化程式可以處理DateTimeOffsets從/到strings和DateTimes(您也可以省略string表示部分)的序列化。您可以在頂部新增您感興趣的任何邏輯。要註冊新的序列化程式,您應該在開始使用MongoCollection之前呼叫以下內容。
BsonSerializer.RegisterSerializer<DateTimeOffset>(new DateTimeOffsetSupportingBsonDateTimeSerializer());
你準備好了。
興趣點
DateTimes時間在MongoDb中表示為自unix紀元以來的毫秒數。.NET框架現在內建了使用這些值從和到DateTimeOffset進行轉換的支援
因此,無論您的DateTimeOffset值是“2018-11-24T14:40:23+05:00”還是“2018-11-24T09:40:23+00:00”,它都會在MongoDB中生成相同的DateTime。
原文地址:https://www.codeproject.com/Tips/1268086/MongoDB-Csharp-Serializer-for-DateTimeOffset-to-Bs