Domanda

Sto usando entità codice del framework primo ed esponendo il database Northwind attraverso un WCF REST HTTP interfaccia.

Non ho esposto la tabella OrderDetails (articoli di ordine), in quanto non ha senso la creazione di un ordine e poi l'aggiunta di ogni richiesta OrderDetail separatamente attraverso un altro servizio. A mio avviso ha bisogno di essere una transazione atomica che o riesce o non riesce come uno. Perciò io includo la collezione Order.OrderDetails quando passa al cliente e assumere ho intenzione di ottenere uno quando un ordine viene creato o aggiornato.

Il problema tuttavia sembra rilevare i cambiamenti nella raccolta OrderDetails quando riattaccare l'entità ordine per un aggiornamento. L'ordine stesso può essere impostato come modificato per aggiornare tali proprietà, ma questo non cascata agli elementi OrderDetail. Così posso andare manualmente attraverso e insieme quelli ai modificati, ma le bugie problema aggiornati nel capire quali sono aggiornati in primo luogo. L'impostazione di una nuova OrderDetail alla modifica causerà un errore quando si cerca di risparmiare.

Ho letto una raccomandazione per impostare l'ID di nuovi elementi di raccolta a 0 e nell'uso server che per decidere se si tratta di nuovo o esistente. Northwind tuttavia utilizza una chiave composta tra OrderID e ProductID per OrderDetails. Questi saranno entrambi devono essere impostati dal cliente, in modo da non riesco a trovare un modo per rilevare che cosa è nuovo. Inoltre, un cancellati OrderDetail non esisterà nel grafico distaccato e avrò bisogno di capire cosa è stato eliminato ed esplicitamente rimuoverlo.

Qualche consiglio sarebbe molto apprezzato.

public override Order Update(Order entity)
{
    dbset.Attach(entity);
    DataContext.Entry(entity).State = EntityState.Modified;

    foreach (var orderDetail in entity.OrderDetails)
    {
        DataContext.Entry(orderDetail).State = EntityState.Modified;
    }

    return entity;
}
È stato utile?

Soluzione

Questa è e complesso problema e non c'è magia che lo farà per voi. La mia soluzione (e l'unico che funziona in tutti gli scenari) è stato quello di caricare di nuovo il Order nel vostro metodo di aggiornamento e unire manualmente le modifiche:

public override Order Update(Order entity)
{
    // No attach of entity

    var attached = DataContext.Orders.Include(o => o.OrderDetails).SingleOrDefault(...);
    if (attached == null) ...

    // Merge changes from entity to attached - if you change any property
    // it will be marked as modified automatically

    foreach (var detail in attached.OrderDetails.ToList())
    {
        // ToList is necessary because you will remove details from the collection

        // if detail exists in entity check if it must be updated and set its state

        // if detail doesn't exists in entity remove if from collection - if it is \
        // aggregation (detail cannot exists without Order) you must also delete it 
        // from context to ensure it will be deleted from the database
    }

    foreach (var detail in entity.OrderDetails)
    {
        // if it doesn't exists in attached create new detail instance,
        // fill it from detail in entity and add it to attached entity - 
        //you must not use the same instance you got from the entity
    }

    DataContext.SaveChanges();

    return entity;
}

Non ci può essere inoltre necessario verificare manualmente timestamp se li si usa.

Scenario alternativo è quello che hai descritto con 0 usato per nuovi dettagli e ID negativo per i dettagli cancellati, ma che è la logica che deve essere fatto sul client. Funziona anche solo in alcuni casi.

Altri suggerimenti

Recentemente ho avuto il permesso di open source un certo lavoro che ho fatto per il mio datore di lavoro qualche tempo fa (con alcuni cambiamenti di rotta). Ho scritto un metodo di estensione per risolvere questo problema, si può ottenere a http://refactorthis.wordpress.com/2012/12/11/introducing-graphdiff-for-entity-framework-code-first -permette--updates automatici-di-un-grafico-di--entità indipendenti /

Speranza che aiuta!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top