Повторное предприятие графика сущностей и обнаружение сбора изменений

StackOverflow https://stackoverflow.com/questions/7804491

Вопрос

Сначала я использую код фреймворта Entity и обнажаю базу данных Northwind через интерфейс WCF REST HTTP.

Я не разоблачал таблицу OrderDetails (пункты заказа), поскольку она не имеет смысла создавать заказ, а затем добавлять каждый требуемый OrderDetail отдельно через другую службу. На мой взгляд, это должна быть атомная транзакция, которая либо преуспевает, либо терпит неудачу как единый. Поэтому я включаю коллекцию Order.OrderDetails при передаче клиенту, и предполагаю, что собираюсь получить его, когда заказ будет создан или обновлен.

Однако проблема, по -видимому, определяет изменения в сборе OrderDetails при переборе объекта Order для обновления. Сам заказ может быть установлен как измененный для обновления этих свойств, но это не каскаднее для элементов OrderDetail. Таким образом, я могу вручную пройти и установить обновленные для изменения, но проблема заключается в выяснении, какие из них обновляются в первую очередь. Установка нового OrderDetail для изменения будет вызвать ошибку при попытке сохранить.

Я прочитал рекомендацию, чтобы установить идентификатор новых элементов коллекции на 0, и на сервере используйте это, чтобы решить, новым или существующим. Однако Northwind использует композитный ключ между OrderID и ProductID для OrderDetails. Они оба должны быть установлены клиентом, поэтому я не могу найти способ обнаружить то, что нового. Кроме того, удаленный OrderDetail не будет существовать на отдельном графике, и мне нужно будет выяснить, что было удалено, и явно удалить его.

Любые советы будут высоко ценится.

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;
}
Это было полезно?

Решение

Это общая и сложная проблема И нет магии, которая сделает это для вас. Моим решением (и единственным, которое работает во всех сценариях) было загрузить Order Опять же в вашем методе обновления и вручную объединять изменения:

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

Также может быть необходимо вручную проверить временные метки, если вы их используете.

Альтернативный сценарий - это то, что вы описали с 0, используемым для новых деталей и отрицательного идентификатора для удаленных деталей, но это логика, которая должна быть сделана на клиенте. Это также работает только в некоторых случаях.

Другие советы

Недавно мне разрешили открыть некоторую работу, которую я выполнил для своего работодателя некоторое время назад (конечно, с некоторыми изменениями). Я на самом деле написал метод расширения для решения этой проблемы, вы можете получить ее по http://refactorthis.wordpress.com/2012/12/11/introducing-graphdiff-for-entity-framework-code-first-allowing-automated-updates of-a-of-detached-entities/

Надеюсь, поможет!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top