2017-11-24 1 views
1

Ich verwende die DocumentDB API von Cosmos DB in Azure. Dokumente werden von einem EventHub entnommen und von einer Azure-Funktion, die von diesem EventHub ausgelöst wird, in der Datenbank gespeichert.Cosmos/Document Db Client ignoriert JsonConverter für Enums

Die Dokumente, die ich speichere, enthalten auch ein paar Enums. Leider werden diese Enum-Werte mit ihrer Indexnummer anstelle von Enum-Werten serialisiert (siehe hier: https://i.stack.imgur.com/3nP9o.png). Genauer gesagt geschieht dies, wenn die Funktion in Azure ausgeführt wird. Tests in einer lokalen IDE funktionieren einwandfrei.

Dies ist der Code, der Cosmos/DocumentDB schreibt:

DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey); 
... 
var response = DocumentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), tick); 
response.Wait(); 

"tick" ist die genannte Aufgabe gespeichert werden.

versuchte ich ein paar Dinge, die Dokument-Client serialisiert Aufzählungen richtig zu machen:

  • Annotation bei Enum Eigenschaft:

    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] 
    public OrderActionEnum? Action { get; set; } 
    
  • Annotation bei Enum Defintion:

    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] 
    public enum OrderActionEnum 
    { 
        NEW, 
        CHANGE, 
        DELETE, 
        SNAPSHOT, 
        INITIAL 
    } 
    
  • Übergabe des Konverters an den Konstruktor des Document db client:

    DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey,     
        new JsonSerializerSettings 
        { 
         Converters = new List<JsonConverter> {new StringEnumConverter()} 
        }); 
    
  • Einrichten eines Standard-Serializer:

    JsonConvert.DefaultSettings =() => new JsonSerializerSettings 
    { 
        Converters = new List<JsonConverter> {new StringEnumConverter()} 
    }; 
    

Keiner dieser Versuche überzeugte die Cosmos/DocumentDB die ENUM-Werte zu speichern.

Ein interessanter Effekt war, dass die dritte Variante (Konverter Konstruktor DocumentClient vorbei) in Ausnahmefällen führte, wenn Azure ausgeführt wird (lokale Tests funktionierte gut):

2017-11-24T15:08:55.291 System.MissingMethodException : Method not found: 'Void Microsoft.Azure.Documents.Client.DocumentClient..ctor(System.Uri, System.String, Newtonsoft.Json.JsonSerializerSettings, Microsoft.Azure.Documents.Client.ConnectionPolicy, System.Nullable`1<Microsoft.Azure.Documents.ConsistencyLevel>)'. 
    at TickAnalysis.DataManager.Persistency.AbstractCosmosClient`1..ctor(ILogger logger,String dbServiceEndpoint,String dbAuthKey,String databaseId,String collectionId) 
    at TickAnalysis.DataManager.DataManagerFunction.RunStoreOrderEvent(String message,TraceWriter log) 

Das sah ein bisschen wie verschiedene Versionen der Paket Microsoft.Azure.DocumentDB wird verwendet. Also habe ich die DLLs in meinem lokalen Bin mit denen verglichen, die für die Funktion in Azure bereitgestellt wurden. In beiden Fällen war es Version 1.19.1.

Jetzt sind mir die Ideen ausgegangen. Ich könnte die Enums durch einfache Zeichenfolge ersetzen, aber das möchte ich wirklich nicht. Irgendwelche Hinweise werden geschätzt.

Mir sind ähnliche Fragen bekannt, die vorher gefragt werden.Zum Beispiel:

Leider kein thes e löste mein Problem.

Antwort

0

Sie sollten Azure-Funktionen Cosmos DB-Ausgabebindung verwenden, um Ihr Dokument zu speichern. Das folgende Beispiel funktioniert wie erwartet (speichert den Enum-Wert als Zeichenfolge).

-Code run.csx:

#r "Newtonsoft.Json" 

using System.Net; 
using Newtonsoft.Json; 
using Newtonsoft.Json.Converters; 

public class Doc 
{ 
    public string id { get; set; } 

    [JsonConverter(typeof(StringEnumConverter))] 
    public OrderActionEnum Action { get; set; } 
} 

public enum OrderActionEnum { NEW, CHANGE } 

public static HttpResponseMessage Run(HttpRequestMessage req, out Doc outputDocument) 
{ 
    outputDocument = new Doc { id = "111", Action = OrderActionEnum.CHANGE }; 
    return req.CreateResponse(HttpStatusCode.OK); 
} 

Bindungen function.json:

{ 
    "bindings": [ 
    { 
     "authLevel": "function", 
     "name": "req", 
     "type": "httpTrigger", 
     "direction": "in" 
    }, 
    { 
     "name": "$return", 
     "type": "http", 
     "direction": "out" 
    }, 
    { 
     "type": "documentDB", 
     "name": "outputDocument", 
     "databaseName": "testdb", 
     "collectionName": "test", 
     "createIfNotExists": false, 
     "connection": "my_DOCUMENTDB", 
     "direction": "out" 
    } 
    ], 
    "disabled": false 
} 

Produziert Dokument:

{ 
    "id": "111", 
    "Action": "CHANGE" 
} 
+0

Hallo Mikhail! Danke für Ihre Antwort! In der Tat war mir die Möglichkeit nicht bekannt, eine Ausgabebindung zu konfigurieren. Meine Entschuldigung ist, dass ich Azure und C# ziemlich neu bin. Allerdings frage ich mich, ob Ihr vorgeschlagener Ansatz für mich machbar ist. Abhängig vom Inhalt des Dokuments und dem, was bereits in der Datenbank vorhanden ist, muss ich verschiedene Operationen aufrufen. Manchmal wird nur ein neues Dokument hinzugefügt, aber manchmal muss ich etwas aktualisieren oder löschen. Es scheint mir, dass dies mit der Ausgabebindung nicht möglich ist. Ich frage mich auch, wie das Deployment mit VSTS funktionieren würde. –

0

ich eine Abhilfe gefunden, dass mein Problem gelöst:

  • Serialize das Objekt, das in einen JSON-String gespeichert werden soll ...
  • ... dann deserialisieren es in ein generisches JObject ...
  • ... und dann, dass speichern.

-Code sieht wie folgt aus:

DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey); 
... 
var jsonString = JsonConvert.SerializeObject(tick); 
var jObject = JsonConvert.DeserializeObject(jsonString); 
var response = DocumentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), jObject); 
response.Wait(); 

Die Aufzählungen in blanke Saiten durch diesen Ansatz transformiert werden. Nicht sehr nett, aber nach all der Frustration bin ich zufrieden mit dieser Lösung. Und zumindest musste ich keinen anderen Ort wechseln.

Verwandte Themen