使用 EF Core Azure Cosmos DB 提供程序中的非结构化数据Working with Unstructured Data in EF Core Azure Cosmos DB Provider

EF Core 旨在使使用在模型中定义的架构的数据变得简单。 但 Azure Cosmos DB 的优点之一是存储数据形状的灵活性。

访问原始 JSONAccessing the raw JSON

可以通过名为 "__jObject"卷影状态JObject 包含表示从存储区接收的数据的特定属性来访问不 EF Core 跟踪的属性,以及将存储的数据:

  1. using (var context = new OrderContext())
  2. {
  3. await context.Database.EnsureDeletedAsync();
  4. await context.Database.EnsureCreatedAsync();
  5. var order = new Order
  6. {
  7. Id = 1,
  8. ShippingAddress = new StreetAddress { City = "London", Street = "221 B Baker St" },
  9. PartitionKey = "1"
  10. };
  11. context.Add(order);
  12. await context.SaveChangesAsync();
  13. }
  14. using (var context = new OrderContext())
  15. {
  16. var order = await context.Orders.FirstAsync();
  17. var orderEntry = context.Entry(order);
  18. var jsonProperty = orderEntry.Property<JObject>("__jObject");
  19. jsonProperty.CurrentValue["BillingAddress"] = "Clarence House";
  20. orderEntry.State = EntityState.Modified;
  21. await context.SaveChangesAsync();
  22. }
  23. using (var context = new OrderContext())
  24. {
  25. var order = await context.Orders.FirstAsync();
  26. var orderEntry = context.Entry(order);
  27. var jsonProperty = orderEntry.Property<JObject>("__jObject");
  28. Console.WriteLine($"First order will be billed to: {jsonProperty.CurrentValue["BillingAddress"]}");
  29. }
  1. {
  2. "Id": 1,
  3. "PartitionKey": "1",
  4. "TrackingNumber": null,
  5. "id": "1",
  6. "Address": {
  7. "ShipsToCity": "London",
  8. "ShipsToStreet": "221 B Baker St"
  9. },
  10. "_rid": "eLMaAK8TzkIBAAAAAAAAAA==",
  11. "_self": "dbs/eLMaAA==/colls/eLMaAK8TzkI=/docs/eLMaAK8TzkIBAAAAAAAAAA==/",
  12. "_etag": "\"00000000-0000-0000-683e-0a12bf8d01d5\"",
  13. "_attachments": "attachments/",
  14. "BillingAddress": "Clarence House",
  15. "_ts": 1568164374
  16. }

警告

"__jObject" 属性是 EF Core 基础结构的一部分,只应用作最后的手段,因为在将来的版本中可能会有不同的行为。

备注

对实体所做的更改将覆盖 SaveChanges期间 "__jObject" 中存储的值。

使用 CosmosClientUsing CosmosClient

若要完全分离 EF Core 获取 DbContextAZURE COSMOS DB SDK 的一部分CosmosClient对象:

  1. using (var context = new OrderContext())
  2. {
  3. var cosmosClient = context.Database.GetCosmosClient();
  4. var database = cosmosClient.GetDatabase("OrdersDB");
  5. var container = database.GetContainer("Orders");
  6. var resultSet = container.GetItemQueryIterator<JObject>(new QueryDefinition("select * from o"));
  7. var order = (await resultSet.ReadNextAsync()).First();
  8. Console.WriteLine($"First order JSON: {order}");
  9. order.Remove("TrackingNumber");
  10. await container.ReplaceItemAsync(order, order["id"].ToString());
  11. }

缺少属性值Missing property values

在上面的示例中,我们从顺序中删除了 "TrackingNumber" 属性。 由于在 Cosmos DB 中索引的工作原理,引用缺少的属性的其他位置的查询可能会返回意外的结果。 例如:

  1. using (var context = new OrderContext())
  2. {
  3. var orders = await context.Orders.ToListAsync();
  4. var sortedOrders = await context.Orders.OrderBy(o => o.TrackingNumber).ToListAsync();
  5. Console.WriteLine($"Number of orders: {orders.Count}");
  6. Console.WriteLine($"Number of sorted orders: {sortedOrders.Count}");
  7. }

排序的查询实际上不返回任何结果。 这意味着,当直接使用存储时,应注意始终填充由 EF Core 映射的属性。

备注

在未来版本的 Cosmos 中,此行为可能会发生变化。 例如,当前如果索引策略定义了复合索引 {Id/? ASC,TrackingNumber/? ASC)},则为 “ORDER BY c.Id ASC,ASC” 的查询__将__返回缺少 "TrackingNumber" 属性的项。