Репозиторий + UnitOfWork + EF Обновление основной записи при изменении подробных записей. (TotalAmount = Sum (Amount)) - PullRequest
0 голосов
/ 13 марта 2011

Я пытаюсь реализовать шаблоны Repository и UnitOfWork с использованием Entity Framework.

Это сценарий:

Пользователь может добавлять или изменять подробные записи в главном окне подробностей, и при нажатии «сохранить» добавленные / измененные записи отправляются на сервер.

Затем я выполняю CreateOrUpdateMultiple (). CreateMultiple добавить новые записи в хранилище. UpdateMultiple извлекает записи, которые будут обновлены.

После завершения двух операций мне нужно обновить основную запись суммой (полем) со всеми подробными записями. (Под всем я имею в виду существующие, которые не были изменены, и те, которые были в памяти)

Это то, что я до сих пор думал ...

  1. Будучи пуристом с шаблоном репозитория, я должен извлечь все подробные записи, а затем смешать в одном списке существующие записи (измененные или нет) и добавленные, а затем выполнить операцию суммирования, но что если поле количества подробных записей является вычисляемым полем базы данных?

  2. Чтение из базы данных только записей, подлежащих обновлению (думая, что это будет быстрее, потому что если у меня будет 40 записей, и только 3 будут изменены, а 2 добавлены, я не буду читать весь набор), а затем как-то выполнить обновление основной записи, но проблема в том, что эти записи еще не в базе данных.

У меня есть только один экземпляр ObjectContext для всех операций, и я вызываю SaveChanges () в моем сервисе для фиксации всего за одну транзакцию.

Что вы мне посоветуете сделать? Или как вы справляетесь с такой ситуацией?

Заранее спасибо

// Update

Здесь более технически описано

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

//Service Layer
Method()
{
   Method1.Invoke(masterRecordId, detaildRecords); //
}

//Business Layer
Method1(masterRecordId, detailRecords)
{
     using(TransactionScope ts = new TransactionScope())
     {
          var recordsToUpdate = dal.RetrieveOnlyRecordsToUpdate();

          //Update retrieved records with the values of recods comming from the client
          dal.Update(recordsToUpdate); //ctx.ApplyChanges(); and ctx.SaveChanges();

          dal.Add(recordsToAdd) //ctx.Add(detail records); and ctx.SaveChanges();

          //Update master record TotalSum
          dal.UpdateMasterRecord(masterRecordId); //Here is performed ctx.ExecuteStoredCommand("UPDATE MasterTable = SUM() WHERE MasterRecordId = {0}")...

          Method2();

          ts.Complete();
     }
}

Method2(masterRecordId)
{
     using(TransactionScope ts = new TransactionScope())
     {
          MasterRecord m = Retrieve(masteRecordId);
          Notification notification = new Notification(){ ...assign properties..., m.TotalSum};

          dal.Add(notification); //ctx.Add(notification); and ctx.SaveChanges();

          ts.Complete(); 
     }
}

Это то, что я хочу сделать ...

//Service Layer
Method()
{
  Method1.Invoke(masterRecordId, detail records);

  UnitOfWorkManager.Current.Commit(); //
}

//Business Layer
Metodo1(masterRecordId, detail records)
{
          MasterRecord masterRecord = repository.Retrieve(masterRecordId);

          var recordsToUpdate = repository.RetrieveOnlyRecordsToUpdate();

          //Update retrieved records with the values of recods comming from the client
          repository.Modify(recordsToUpdate); 

          repository.Add(recordsToAdd); 

          //Here i'm stuck and i'm thinking it should be something like this.
          masterRecord.TotalSum = sum(detailRecords in memory + detail records in database); //
          repository.Modify(masterRecord); //

          or

          //Another way somehow...

          //Then keep going with the udpated master record
          Method2(masterRecord);
     }
}

Method2(masterRecord)
{
     //Create notification
     var notification = new Notification(){ ...properties.., masterRecord.TotalSum};
     repository.Add(notification);
}

1 Ответ

0 голосов
/ 15 марта 2011

Если вы хотите сделать это как транзакцию и вызвать SaveChanges только один раз, вы должны сделать это в своем приложении до вызова SaveChanges.Поэтому, как правило, вы должны получить сумму, прежде чем вносить какие-либо изменения, и изменять ее с помощью обновленных значений, вставленных значений и удаленных значений.Затем вы установите новое значение суммы в основную запись.Если вы сделаете это таким образом, у вас будет единица работы.

Почему другие подходы не так хороши.

  • Вычисляемое поле в базе данных.Это потребует ручной перезагрузки главной сущности после операции сохранения, поскольку при сохранении подробностей невозможно перезагрузить изменения в другой сущности.Более того, для логики базы данных, вероятно, потребуется триггер в таблице сведений для изменения суммы в основной таблице.
  • Обновление основной записи после сохранения изменений в деталях разбивает единицу работы.
...