Как я могу обновить и сохранить дочерний объект в EF CosmosDB?

#c# #entity-framework #azure-cosmosdb

Вопрос:

У меня есть простые родительские отношения «один к одному» в документе Cosmos. Тип документа есть Invoice , и у него есть один вызываемый дочерний объект BillLocation . Когда я обновляю какое-то свойство в принадлежащем местоположении счета, а затем сохраняю объект счета-фактуры, все выглядит странно.

             var invoice = await db.Invoices.FindAsync("invoice1");
            invoice.BillLocation.City = "something";

            log("Pre save: Invoice     : "   db.Entry(invoice ).State);
            log("Pre save: BillLocation: "   db.Entry(invoice .BillLocation).State);

            await db.SaveChangesAsync();

            log("Pos save: Invoice     : "   db.Entry(invoice ).State);
            log("Pos save: BillLocation: "   db.Entry(invoice .BillLocation).State);

            // Invoice is now Modified after the save!!!
            // Save again will save Invoice object *again*. This causes EF to throw 
            // DbUpdateConcurrencyException
            await db.SaveChangesAsync(); 
            log("Done!");

 

Выход:

 Pre save: Invoice     : Unchanged
Pre save: BillLocation: Modified
Pos save: Invoice     : Modified    <---- WHAT???
Pos save: BillLocation: Unchanged

[Exception thrown: DbUpdateConcurrencyException Conflicts for item with id 'Invoice|invoice1'.]
 

(Причина, по которой он запускается, заключается в том, что запускается проверка параллелизма ETag. Но реальная проблема заключается в том, что состояние invoice переходит от неизменного к измененному после завершения сохранения.)

Я предполагаю, что делаю здесь что-то не так.

Я пробовал это с EF3 и последней версией для dotnet6. Они оба так себя ведут.

Сохраненный документ выглядит по существу следующим образом

 {
   "InvoiceNumber" : "invoice1",
   "CustomerID" : "...",
   "BillLocation": {
       "City": "something"
   }
}
 

Контекст таков:

             modelBuilder.Entity<Invoice>()
                .ToContainer("Invoices")
                .UseETagConcurrency()
                .HasPartitionKey(x => x.CustomerId)
                .HasKey(x => x.InvoiceNumber);
            modelBuilder.Entity<Invoice>().OwnsOne(o => o.BillLocation);
 

Так что же происходит?