2017-03-08 1 views
1

Ich versuche, ein Löschen einer Hierarchie von Objekten zu tun:setDeleted Schleife in modifizierten Einheiten, was zu savechanges nennen

Customer-> Orders-> OrderItems-> OrderItemOptions

ich eine einfache verschachtelte Schleife einrichten versuchen, die Operationen sogar in der "korrekten" Reihenfolge auszuführen, wie sie in der Datenbank ausgeführt werden müssten - Löschen von Kinddatensätzen zuerst, bevor Eltern gelöscht werden.

Hier ist die Schleife:

deleteCustomer(customer: Customer): Promise<void> { 
    return this.getCustomerOrderHistory(customer.id).then(orders => { 
    orders.forEach(o => { 
     o.items.forEach(oi => { 
     oi.options.forEach(opt => opt.entityAspect.setDeleted()); 
     oi.entityAspect.setDeleted(); 
     }); 
     o.entityAspect.setDeleted(); 
    }); 
    customer.entityAspect.setDeleted(); 
    }); 
} 

Das Problem ist, dass, wenn das übergeordnete Objekt auf jeder Ebene setDeleted ist(), eine Reihe von doppelten Entitätsdatensätze markiert als „modifiziert“ auf die Änderungen durch die gepufferte hinzugefügt werden EntityManager. Wenn ich dann saveChanges aufruft, löst das Backend von ASP.NET/EF eine Ausnahme aus, weil zu dem Zeitpunkt, zu dem die UPDATE-Anweisungen dieser modifizierten Datensätze ausgeführt werden, die DELETEs bereits geschehen sind und die UPDATEs mit einer nicht gefundenen Ausnahme fehlschlagen.

Also was fehlt mir hier?

Antwort

1

Dies ist ein klassischer Fall, bei dem ein Array modifiziert wird, während darüber iteriert wird. Wenn wir Kinder wie diese löschen:

o.items.forEach(oi => { 
     oi.entityAspect.setDeleted(); 
    }); 

... jedes Mal, wenn wir setDeleted nennen, entfernt sie das Kind Entität aus der Mutter items Sammlung, die die Kollektion iteriert wird, ist. Daher überspringt die nächste Iteration die Entität dazwischen, und nur ungefähr die Hälfte der Entitäten wird tatsächlich gelöscht. Die Symptome hierfür wären ein SaveBundle, das eine Mischung gelöschter und geänderter Entitäten enthält, und (wenn Sie die übergeordnete Entität löschen) eine Fremdschlüsselverletzung aus der Datenbank, wenn Sie versuchen, die übergeordnete Entität zu löschen, ohne alle zu löschen die Kinder.

Die einfache Lösung besteht darin, vor dem Iterieren eine Kopie des Arrays zu erstellen, z.B. mit slice:

o.items.slice().forEach(oi => { 
     oi.entityAspect.setDeleted(); 
    }); 
+0

Danke Steve, das war genau das Problem. Ich wusste, dass Breeze Kinder/Eltern-Beziehungen hinzufügen oder entfernen kann, indem sie entweder die FK-Eigenschaft (dh order.customerId) oder die nav-Eigenschaft (dh order.customer) oder beide setzt, also dachte, dass etwas so läuft, aber nicht konnte Finde warum. –

Verwandte Themen