EF4 — Как «прикрепить» сущности из разных ObjectContext вместе, чтобы сохранить их все в одной транзакции?

#entity-framework-4 #transactions

#entity-framework-4 #транзакции

Вопрос:

Я хочу создать модульное приложение и хотел бы создать несколько EDMX, используя только подмножество таблиц, необходимых в этом конкретном контексте.

Например.

  • EDMX для инвойсов: таблица Invoice, InvoiceDetails, Customer
  • EDMX для заказов: таблица заказов, детали заказов, Клиент
  • и т.д.

Таким образом, я уменьшаю размер и управляю (я думаю)

Но мне может потребоваться создать универсальный модуль, который выполняет пакетную операцию над несколькими объектами, возможно, распределенный по нескольким EDMX. Например. Консолидировать клиентов — объединить несколько клиентов в один клиент (возможно, пользователи несколько раз по ошибке вводили один и тот же клиент, или я хочу объединить две клиентские учетные записи и т.д.)

Для этого я хочу использовать шаблон ServiceLocator

  1. определите интерфейс, IClientMerger
  2. и когда я создаю новую сущность, которая ссылается на client, я также создаю новый обработчик IClientMerger
  3. когда мне нужно дедуплицировать, я загружаю все ICLientHandlers и вызываю их в цикле, и они заменяют старый ClientID новым ClientID в обрабатываемом объекте (один в счетах, один в заказах и т.д.).

Все в порядке, но я хочу упаковать все это в транзакцию, чтобы все было сохранено или нет. находясь в отдельном EDMX, как я могу упаковать их все в одну транзакцию? Должен ли я вручную создать ADO.NET транзакция и вызов ObjectContext.SaveChanges для всего EDMX внутри? Или есть другой, более элегантный способ?

Спасибо

Ответ №1:

 using(TransactionScope tran = new TransactionScope())
{
  //do some work...
  context1.SaveChanges()
  context2.SaveChanges()

  tran.Commit()
}
  

Если до удаления TransactionScope не было фиксации, транзакция автоматически откатывается.

Контексты могут работать даже на разных серверах sql, если доступен MS DTC.

Ответ №2:

Попробуйте класс TransactionScope.
Вам понадобится требуемая TransactonScopeOption.