Arbeiten mit unstrukturierten Daten im EF Core Azure Cosmos DB-Anbieter

EF Core wurde entwickelt, um die Arbeit mit Daten zu erleichtern, die auf ein im Modell definiertes Schema folgen. Einer der Stärken von Azure Cosmos DB ist jedoch die Flexibilität in Form der gespeicherten Daten.

Zugreifen auf den unformatierten JSON-Code

Hinweis

Die "__jObject" Schatteneigenschaft wurde in EF Core 11 entfernt. Ausführliche Informationen finden Sie unter "Grundlegende Änderungen in EF Core 11 ".

In EF Core 10 und früheren Versionen war es möglich, auf Eigenschaften zuzugreifen, die von EF Core nicht über eine spezielle Eigenschaft im Schattenzustand"__jObject" nachverfolgt werden, die eine JObject Darstellung der daten enthielt, die aus dem Speicher empfangen wurden, und auf Daten, die gespeichert werden sollen:

using (var context = new OrderContext())
{
    await context.Database.EnsureDeletedAsync();
    await context.Database.EnsureCreatedAsync();

    var order = new Order
    {
        Id = 1, ShippingAddress = new StreetAddress { City = "London", Street = "221 B Baker St" }, PartitionKey = "1"
    };

    context.Add(order);

    await context.SaveChangesAsync();
}

using (var context = new OrderContext())
{
    var order = await context.Orders.FirstAsync();
    var orderEntry = context.Entry(order);

    var jsonProperty = orderEntry.Property<JObject>("__jObject");
    jsonProperty.CurrentValue["BillingAddress"] = "Clarence House";

    orderEntry.State = EntityState.Modified;

    await context.SaveChangesAsync();
}

using (var context = new OrderContext())
{
    var order = await context.Orders.FirstAsync();
    var orderEntry = context.Entry(order);
    var jsonProperty = orderEntry.Property<JObject>("__jObject");

    Console.WriteLine($"First order will be billed to: {jsonProperty.CurrentValue["BillingAddress"]}");
}
{
    "Id": 1,
    "PartitionKey": "1",
    "TrackingNumber": null,
    "id": "1",
    "Address": {
        "ShipsToCity": "London",
        "ShipsToStreet": "221 B Baker St"
    },
    "_rid": "eLMaAK8TzkIBAAAAAAAAAA==",
    "_self": "dbs/eLMaAA==/colls/eLMaAK8TzkI=/docs/eLMaAK8TzkIBAAAAAAAAAA==/",
    "_etag": "\"00000000-0000-0000-683e-0a12bf8d01d5\"",
    "_attachments": "attachments/",
    "BillingAddress": "Clarence House",
    "_ts": 1568164374
}

Warnung

Die "__jObject" Eigenschaft war Teil der EF Core-Infrastruktur. Sie ist nur in EF Core 10 und früher vorhanden und wurde ab EF Core 11 entfernt.

Verwenden von CosmosClient

Um vollständig von EF Core abzukoppeln, rufen Sie das CosmosClient-Objekt ab, das Teil des Azure Cosmos DB SDK ist von DbContext:

using (var context = new OrderContext())
{
    var cosmosClient = context.Database.GetCosmosClient();
    var database = cosmosClient.GetDatabase("OrdersDB");
    var container = database.GetContainer("Orders");

    var resultSet = container.GetItemQueryIterator<JObject>(new QueryDefinition("select * from o"));
    var order = (await resultSet.ReadNextAsync()).First();

    Console.WriteLine($"First order JSON: {order}");

    order.Remove("TrackingNumber");

    await container.ReplaceItemAsync(order, order["id"].ToString());
}

Fehlende Eigenschaftswerte

Im vorherigen Beispiel wurde die "TrackingNumber" Eigenschaft aus der Reihenfolge entfernt. Aufgrund der Funktionsweise der Indizierung in Azure Cosmos DB können Abfragen, die auf die fehlende Eigenschaft verweisen, an einer anderen Stelle als in der Projektion unerwartete Ergebnisse zurückgeben. Beispiel:

using (var context = new OrderContext())
{
    var orders = await context.Orders.ToListAsync();
    var sortedOrders = await context.Orders.OrderBy(o => o.TrackingNumber).ToListAsync();

    Console.WriteLine($"Number of orders: {orders.Count}");
    Console.WriteLine($"Number of sorted orders: {sortedOrders.Count}");
}

Die sortierte Abfrage gibt tatsächlich keine Ergebnisse zurück. Dies bedeutet, dass man beim direkten Arbeiten mit dem Speicher stets die von EF Core zugeordneten Eigenschaften auffüllt.

Hinweis

Dieses Verhalten kann sich in zukünftigen Versionen von Azure Cosmos DB ändern. Beispielsweise, wenn die Indizierungsrichtlinie den zusammengesetzten Index {Id/?} definiert. ASC, TrackingNumber/? ASC)}, dann würde eine Abfrage mit "ORDER BY c.Id ASC, c.Discriminator ASC" Elemente zurückgeben, die die "TrackingNumber" Eigenschaft fehlen.