работа с неструктурированными данными в поставщике EF Core Azure Cosmos DB

EF Core был разработан для упрощения работы с данными, которые следуют за схемой, определенной в модели. однако одним из достоинств Azure Cosmos DB является гибкость в форме хранимых данных.

Доступ к необработанному JSON

Доступ к свойствам, которые не отслеживанию, можно получить, EF Core с помощью специального свойства в теневом состоянии с именем , которое содержит JObject данные, полученные из хранилища и данные, которые будут сохранены:

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
}

Предупреждение

"__jObject"Свойство является частью инфраструктуры EF Core и должно использоваться только в качестве последнего средства, так как в будущих выпусках, скорее всего, будет происходить другое поведение.

Примечание

Изменения в сущности будут переопределять значения, хранящиеся в "__jObject" во время SaveChanges .

Использование Космосклиент

чтобы полностью отделить от EF Core получить объект космосклиент , который является частью пакета SDK для Azure Cosmos DB , из :

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());
}

Отсутствующие значения свойств

В предыдущем примере мы удалили "TrackingNumber" свойство из заказа. из-за того, как индексирование работает в Cosmos DB, запросы, ссылающиеся на отсутствующее свойство в другом месте, чем в проекции, могут возвращать непредвиденные результаты. Пример:

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}");
}

Отсортированный запрос фактически не возвращает результатов. Это означает, что необходимо всегда заполнять свойства, сопоставленные EF Core при непосредственной работе с хранилищем.

Примечание

Это поведение может измениться в будущих версиях Cosmos. Например, в настоящее время, если политика индексирования определяет составной индекс {ID/? ASC, Траккингнумбер/? ASC)}, затем запрос с предложением ORDER BY c.Id ASC, c. дискриминатор ASC "возвратит элементы, у которых отсутствует свойство.