0

Ich versuche, eine generische Wrapper-Bibliothek (C# /. NET) für AWS DynamoDB zu erstellen, die als DAL (Data Access Layer) fungieren kann. Die Anwendungen, die diese Bibliothek verwenden, sind nicht eng mit AWS-Bibliotheken gekoppelt, da die Möglichkeit besteht, dass sie später geändert werden können.Amazon Dynamo DB persistent ORM

Die Struktur von Methoden aus der Hüllklasse werden sollen InsertItem < T> (Objekt), UpdateItem < T> (Objekt) , DeleteItem < T> (id/Objekt exponiert), Liste < T> GetAll(), T GetByParameter < T> (Id).

Ich sehe, dass es drei Ansätze gibt, AWS DynamoDB-Dienste mit AWSSDK zu verwenden.

Approach (1): Low-Level-Zugriff - konvertiert Modell aws hashmap Eingangsstruktur und ruft getItem()/putItem().

Approach (2): High Level Access-Dokument verwenden - konvertieren Modell aws Dokumentenmodell und Dokumentobjekt aws vorbei.

Approach (3): Hochrangigen Zugang Persistenz mit - Mit Attribut DynamoDBTable in Modellmodell DynamoDB Tabelle abzubilden und Linq Betrieb mit bekommen/Aktualisierungstabelle.

In Ansatz (1) & (2) finde ich es schwierig, das Modell DynamoDB-Tabelle zuzuordnen. Im Ansatz (3) sehe ich, dass ich die DynamoDB-Attribute in die Modellklasse in der Anwendung einbeziehen muss, um sie eng gekoppelt zu machen.

Gibt es eine Möglichkeit, in diesen Fällen ein Mapping in Runtime zu erstellen, oder gibt es einen anderen Ansatz?

Ich dachte auch, ob ich json serialize/deserialize das Modell und in dynamoDB einfügen (In diesem Fall gäbe es nur 2 Spalten - ID, JSON Körper für jedes Modell).

Bitte korrigieren Sie mich, wenn ich falsch liege oder etwas verpasst habe.

+0

Wir haben an Dynamo geschrieben, aber nicht gelesen. Unter Verwendung des Persistenzmodells haben wir eine generische Klasse an der DAL (nennen wir sie Log ), die die SDK-Attribute hat und die Anwendung in jeder beliebigen Klasse übergeben kann, und sie wird in der T-Eigenschaft auf dem Log-Objekt gesetzt. Leider versuche ich jetzt, diese Daten zu lesen, und es erweist sich mit Persistenz als schwierig, da ich alle Protokolle sehen möchte, unabhängig von der T auf dem Schreiben verwendet. Das Erstellen einer separaten Leseklasse mit T, die durch Zeichenfolge, Objekt oder Dokument ersetzt wurde, hat nicht funktioniert. Wird Nicht-Persistenz für Lesevorgänge versuchen und wird bei Erfolg aktualisiert. –

+0

Danke für Updates. Lass es mich wissen, wenn du andere Informationen hast. – Sri

Antwort

1

Was folgt, ist die Lösung, die ich voran bringe, minus einige überflüssige Details. Die größte Herausforderung ist das Lesen von Daten beliebiger Typen, da man das nicht einfach vom JSON aus erkennen kann.

In meiner Lösung weiß die konsumierende Anwendung, die die zu schreibenden Typen auswählt, auch, wie der zu deserialisierende Typ beim Lesen identifiziert wird. Dies ist notwendig, da ich mehrere Protokolle verschiedener Typen zurückgeben muss. Daher ist es sinnvoller, JSON an den Konsumenten zurückzugeben und sich damit auseinanderzusetzen. Wenn Sie dies in der DAL angeben möchten, können Sie eine Type-Spalte in der DB hinzufügen und sie mithilfe von Reflection konvertieren, obwohl Sie nach wie vor Probleme haben, Daten für mehrere Typen in einem Aufruf zurückzugeben.

Die Schnittstelle, die wir für den Verbrauch bereitstellen, hat Lese-/Schreibmethoden (Sie können hinzufügen, was Sie sonst noch benötigen).Beachten Sie, dass das Schreiben die Spezifikation von T ermöglicht, aber das Lesen erfordert, dass der Aufrufer deserialisiert, wie oben erwähnt.

public interface IDataAccess 
{ 
    Task WriteAsync<T>(Log<T> log) where T : class, new(); 
    Task<IEnumerable<LogDb>> GetLogsAsync(long id); 
} 

A LogDb Klasse enthält die Persistenz-Attribute:

[DynamoDBTable("TableName")] 
public class LogDb 
{ 
    [DynamoDBHashKey("Id")] 
    public long Id{ get; set; } 

    [DynamoDBProperty(AttributeName = "Data", Converter = typeof(JsonStringConverter))] 
    public string DataJson { get; set; } 
} 

Eine generische Log <T> Klasse für stark typisierte Schreiben verwendet. Die ToDb() - Methode wird in der IDataAccess-Implementierung aufgerufen, um tatsächlich in die DB zu schreiben. Der Konstruktor in einer LogDb nehmen würde durch eine verbrauch Anwendung verwendet werden, die den entsprechenden Typen für die Deserialisierung identifiziert hatten:

public class Log<T> 
    where T : class, new() 
{ 
    public Log() { } 

    public Log(LogDb logDb) 
    { 
     Data = licensingLogDb.OldDataJson.Deserialize<T>(); 
     Id = licensingLogDb.Id; 
    } 

    public long Id { get; set; } 
    public T Data { get; set; } 

    public LogDb ToDb() 
    { 
     string dataJson = Data.Serialize(); 
     return new LogDb 
     { 
      DataJson = dataJson, 
      Id = Id 
     }; 
    } 
} 

Die JsonStringConverter in den Attributen auf LogDb verwendet wandelt die JSON Zeichenfolge in der DataJson Eigenschaft zu und von einem DynamoDB Dokument:

public class JsonStringConverter : IPropertyConverter 
{ 
    public DynamoDBEntry ToEntry(object value) 
    { 
     string json = value as string; 
     return !String.IsNullOrEmpty(json) 
      ? Document.FromJson(json) 
      : null; 
    } 

    public object FromEntry(DynamoDBEntry entry) 
    { 
     var document = entry.AsDocument(); 
     return document.ToJson(); 
    } 
} 

Ein Helfer-Klasse stellt die Serialize und Deserialize Erweiterungen, die JSON.NET der JsonConvert.Serialize/Deserialize verwenden, aber mit null Kontrollen:

public static class JsonHelper 
{ 
    public static string Serialize(this object value) 
    { 
     return value != null 
      ? JsonConvert.SerializeObject(value) 
      : String.Empty; 
    } 

    public static T Deserialize<T>(this string json) 
     where T : class, new() 
    { 
     return !String.IsNullOrWhiteSpace(json) 
      ? JsonConvert.DeserializeObject<T>(json) 
      : null; 
    } 
} 
Verwandte Themen