1. 程式人生 > >MongoDB C#:DateTimeOffset到BsonType DateTime的序列化程式

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的匯入執行,其值包含DateTimeOffsetsXXXXXX +0100)或類似值。雖然我們希望這些值能作為DateTime被儲存在MongoDB中。我們不太關心偏移資訊,儲存的UTC對我們來說很好。

您可以輕鬆在MongoDB中建立自己的DateTimeOffset序列化器並將其註冊為DateTimeOffset序列化器。我會告訴你如何處理。

使用程式碼

您可以檢視MongoDB C#客戶端的原始碼,看看如何構建DateTimeSerializerDateTimeOffset序列化器,並調整其中的內容。最終的序列化程式可能如下所示:

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/stringsDateTimes(您也可以省略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