Linq-to-SQL: использовать общую транзакцию между LinqDataSource и DataContext? - PullRequest
1 голос
/ 11 октября 2010

У меня есть страница, где я использую два элемента управления ASP DetailsView для визуализации данных из двух разных, но связанных, LinqDataSource объектов. Моя основная таблица представлена ​​в первом наборе DetailsView / LinqDataSource, и я использую встроенную функцию обновления LinqDataSource для сохранения изменений, когда DetailsView находится в режиме редактирования. Первичная таблица здесь представляет сущность «Контакт» (то есть лицо или организацию и их контактную информацию).

Второй DetailsView отображает данные из таблицы перекрестных ссылок, которая связывает контакт с одним или несколькими «тегами». Определения тегов взяты из другой таблицы, поэтому таблица перекрестных ссылок просто связывает идентификатор контакта с идентификатором тега; стандартный сценарий типа «многие ко многим».

У меня обновления Tag Xref работают правильно; когда теги добавляются или удаляются из контакта, соответствующие строки вставляются или удаляются из таблицы внешних ссылок. Это достигается не через LinqDataSource, а путем обработки события ItemUpdating для тегов DetailsView и использования DataContext для ручной обработки вставок и удалений.

Таким образом, контакт и теги контакта могут обновляться индивидуально. Проблема в том, что мне нужно обновить контакт и теги Xref, чтобы они произошли вместе в одной транзакции. У меня есть два элемента управления DetailsView, связанных, так что когда пользователь нажимает «Обновить» для первого элемента управления, он запускает обновление для второго. Но первый DetailsView использует связанный LinqDataSource для обновления, который имеет свой собственный DataContext. Попытки «поделиться» DataContext между моим ручным обновлением и результатом LinqDataSource приводят к исключениям ObjectDisposed.

Я чувствую, что упускаю что-то очевидное. Совместное использование объектов DataContext кажется скользким уклоном. Есть ли способ запустить транзакцию на странице, которая будет включать обе операции?

1 Ответ

3 голосов
/ 12 октября 2010

У вас правильный подход.Создайте один объект DataContext ранее в жизненном цикле страницы (я обычно использую конструктор).Добавьте обработчик ContextCreating к обоим LinqDataSource s.В обработчике присвойте свой DataContext свойству ObjectInstance события (см. Также: этот ответ ).Создайте транзакцию, скажем, в событии ItemUpdating :

myDataContext.Connection.Open();
myDataContext.Transaction = myDataContext.Connection.BeginTransaction();

Теперь наступает сложный шаг - когда вас уже запутали.По умолчанию LinqDataSource удалит свой DataContext, когда закончит отправку изменений.Вам необходимо переопределить это поведение, добавив обработчик событий ContextDisposing .В обработчике установите для свойства Cancel события значение true.

Теперь, после завершения работы, вы можете либо зафиксировать, либо откатить транзакцию.(Не забудьте удалить транзакцию.) Наконец, вы можете утилизировать DataContext в Page_Unload.

PS Если вы используете DynamicData , помните, что DynamicDataManager добавляет собственный обработчик к ContextCreating, который создает новый DataContext, тем самым избегая вашей явно созданной транзакции.Раздражает.


В качестве альтернативы, вы можете использовать TransactionScope .Просто создайте новый объект, прежде чем нужно будет выполнить работу, затем вызовите Complete, когда работа будет завершена.Там слишком много магии происходит на мой вкус.Я предпочитаю использовать более явные транзакции DataContext, когда могу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...