Aws-sdk-net: DateTime unterstützt keine Roundtrip-Serialisierung mit dem DocumentModel

Erstellt am 2. Juli 2014  ·  3Kommentare  ·  Quelle: aws/aws-sdk-net

Das DocumentModel Primitive unterstützt die Roundtrip-Serialisierung nicht ordnungsgemäß. Es sollte beim Serialisieren von DateTime den Formatbezeichner "o" verwenden, um sicherzustellen, dass die Zeitzone und Millisekunden korrekt beibehalten werden.

Ich habe unten einen IPropertyConverter erstellt, um die korrekte Serialisierung für DateTime und NullableDateTime zu veranschaulichen.

using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using System.Globalization;

/// <summary>
/// The <see cref="IPropertyConverter"/> to properly support round-trip serialization of <see cref="DateTime"/>.
/// </summary>
public class RoundTripNullableDateTimeTypeConverter : IPropertyConverter
{
    /// <summary>
    /// Converts the <c>value</c> to a <see cref="Primitive"/>.
    /// </summary>
    /// <param name="value">The value to convert.</param>
    /// <returns>The primitive of the <c>value</c>.</returns>
    public DynamoDBEntry ToEntry(object value)
    {
        var date = value as DateTime?;
        return new Primitive 
        {
            Value = date.HasValue ? date.Value.ToString("o", CultureInfo.InvariantCulture) : null
        };
    }

    /// <summary>
    /// Converts the <c>entry</c> to <see cref="DateTime"/>.
    /// </summary>
    /// <param name="entry">The entry to convert.</param>
    /// <returns>The date time of the entry.</returns>
    public object FromEntry(DynamoDBEntry entry)
    {
        var entryString = entry.AsString();
        if (string.IsNullOrEmpty(entryString))
            return null;
        else
            return DateTime.ParseExact(entryString, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
    }
}

/// <summary>
/// The <see cref="IPropertyConverter"/> to properly support round-trip serialization of <see cref="DateTime"/>.
/// </summary>
public class RoundTripDateTimeTypeConverter : IPropertyConverter
{
    /// <summary>
    /// Converts the <c>value</c> to a <see cref="Primitive"/>.
    /// </summary>
    /// <param name="value">The value to convert.</param>
    /// <returns>The primitive of the <c>value</c>.</returns>
    public DynamoDBEntry ToEntry(object value)
    {
        return new Primitive
        {
            Value = ((DateTime)value).ToString("o", CultureInfo.InvariantCulture)
        };
    }

    /// <summary>
    /// Converts the <c>entry</c> to <see cref="DateTime"/>.
    /// </summary>
    /// <param name="entry">The entry to convert.</param>
    /// <returns>The date time of the entry.</returns>
    public object FromEntry(DynamoDBEntry entry)
    {
        return DateTime.ParseExact(entry.AsString(), "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
    }
}

Einige wichtige Referenzen:

Alle 3 Kommentare

Vielen Dank, dass Sie das ansprechen. Wie Sie bereits erwähnt haben, verwendet die aktuelle Implementierung das ISO 8601-UTC-Format, das die Zeitzone nicht speichert und eine geringere Genauigkeit hat als mit dem "o" -Format.

Die ursprüngliche Entscheidung, dieses Format zu verwenden, wurde für alle AWS SDKs getroffen, die eine hochrangige DynamoDB-API implementieren (Tabelle und DynamoDBContext in .NET, DynamoDBMapper in Java usw.). Das Speichern von Daten im ISO 8601 UTC-Format ermöglicht eine konsistente Suche und Sortierung. was nicht möglich ist, wenn Zeitzonen angegeben sind: Größere Zeichenfolgenwerte bedeuten nicht unbedingt "größere" Datumswerte, und es ist möglich, mehrere Darstellungen für ein einzelnes "eindeutiges" Datum zu haben. Letzteres kann bei allen Operationen zu Problemen führen, nicht nur bei Suchen (Abfragen und Scannen): Wenn ein Element mit DateTime als Schlüssel mit einer bestimmten Zeitzone gespeichert wird, kann es nur abgerufen werden, wenn dieselbe exakte Zeitzone verwendet wird. Je nach Struktur einer Anwendung kann eine Änderung der Zeitzone dazu führen, dass alle Datenaufrufe fehlschlagen, da der Schlüssel nicht übereinstimmt.

Die obige Änderung am .NET SDK ist eine entscheidende Änderung für Benutzer, die möglicherweise mehrere SDKs oder verschiedene Versionen des .NET SDK verwenden, da die nicht aktualisierten Clients die neuen Formate nicht analysieren können. Die mitgelieferten Konverter sind jedoch ein ausgezeichneter Ansatz, um Datumsangaben mit höherer Genauigkeit mit Zeitzonen zu speichern, solange die Daten konsistent mit der gleichen Formatierung gelesen und geschrieben werden und einige der genannten Überlegungen berücksichtigt werden.

@PavelSafronov , danke für die Antwort!

Der Grund, warum ich es aufgerufen habe, war ein unerwartetes Verhalten beim Speichern eines UTC-Datums, das beim Abrufen des Elements in der lokalen Zeitzone zurückkam. Dies ist für diejenigen von uns unerwartet, die die API verwenden, um Daten mit UTC ordnungsgemäß zu speichern und abzurufen. Die API geht davon aus, dass eingehende DateTime NICHT UTC sind, daher wird davon ausgegangen, dass es sich bei der Deserialisierung um die Ortszeit handeln sollte. Es macht also eine widersprüchliche Annahme.

Ich habe ein Nuget-Paket namens AWSSDK.DynamoDBv2.Converters zusammengestellt , um anderen zu helfen, die ein konsistentes Serialisierungsverhalten von Daten benötigen. (Die Quelle befindet sich auf GitHub .)

Ich hoffe, diese Informationen helfen dem Team.

Die oben verlinkten Konverter sollten verwendet werden, wenn Sie einen ähnlichen Anwendungsfall wie @radleta haben. Für das Haupt-SDK werden wir die Konvertierungen nicht aktualisieren, da dies eine bahnbrechende Änderung einführt.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen