Как запустить два контекста Entity Framework внутри TransactionScope без MSDTC?
Эта проблема не легко воспроизводится на простом примере, но задавалась вопросом, есть ли у кого-либо опыт и советы, вот в чем проблема:
- с помощью Entity Framework
- имеют много точек в приложении, где (1) данные записываются в таблицу entity, например. Клиент, (2) данные записываются в таблицу История
- оба этих действий используют Entity Framework, ОДНАКО, они используют разные контексты
- эти действия должны быть как в одной транзакции: то есть, если не удается написать, другой не должен писать и т.д.
- Я могу обернуть их TransactionScope,
вот так:
using (TransactionScope txScope = new TransactionScope()) {
...
}
но это дает мне:
Microsoft Distributed Transaction Coordinator (MSDTC) is disabled for network transactions.
Наш администратор базы данных сообщил мне, что MSDTC отключен по выбору и не может быть установлен.
Следовательно, я делаю изменения, пытаясь создать собственное EntityConnection с MetadataWorkspace с мыслью, что каждый контекст будет использовать тот же EntityConnection. Однако это почти невозможно, пытаясь заставить его работать, например. в настоящее время я продолжаю получать вышеупомянутую ошибку, хотя теоретически оба контекста используют EntityConnection. Трудно понять, где/почему Entity Framework требует MSDTC, например.
Кто-нибудь пошел по этому пути раньше, есть опыт или примеры кода, чтобы поделиться?
Ответы
Ответ 1
Ну, проблема довольно проста.
Если вы используете SQL Server 2008, у вас не должно быть этой проблемы, потому что у вас есть продвигаемая транзакция, и, поскольку .NET знает, что вы используете одно и то же хранилище сохранения (базу данных), оно не будет распространять его на DTC и фиксировать как локальный, просмотрите продвигаемую транзакцию с SQL Server 2008.
Насколько я знаю, Oracle работает в своем драйвере для поддержки продвигаемых транзакций, но я не знаю состояния, драйвер MS oracle не поддерживает его.
http://www.oracle.com/technology/tech/windows/odpnet/col/odp.net_11.1.0.7.20_twp.pdf
Если вы используете драйвер, который не поддерживает продвигаемые транзакции,.NET не может использовать локальную транзакцию, выполняющую два подключения. Вы должны изменить свою архитектуру или убедить администратора базы данных для установки MSDTC.
Ответ 2
У меня была аналогичная проблема с SQL 2008, Entity Framework.
У меня были две фреймворки, определенные (EF1 и EF2), но с использованием идентичных строк подключения к базе данных sql 2008.
Я получил ошибку MSDTC выше, при использовании вложенных "приложений" для обоих.
например, код выглядит следующим образом:
using (TransactionScope dbContext = new TransactionScope())
{
using (EF1 context = new EF1())
{
// do some EF1 db call
using (EF2 context2 = new EF2())
{
// do some EF2 db call
}
}
dbContext.Complete();
}
Это было не так просто, потому что это было разделено на несколько методов, но это была основная структура "usings".
Исправление должно было открывать только одно за раз. Нет ошибки MTDSC, нет необходимости открывать распределенные транзакции на db.
using (TransactionScope dbContext = new TransactionScope())
{
using (EF1 context = new EF1())
{
// do some EF1 db call
}
using (EF2 context2 = new EF2())
{
// do some EF2 db call
}
dbContext.Complete();
}
Ответ 3
Я думаю, что вам нужно сделать, чтобы ваши контексты использовали одно соединение с базой данных. Затем вы сможете выполнить эти две операции в двух разных контекстах в одной транзакции. Вы можете достичь этого, передав один объект EntityConnection обоим конструкторам контекста. Конечно, этот подход потребует от вас передать этот объект методам, которые обновляют БД.
Недавно я добавил blogged о создании области контекста базы данных, которая упростит использование нескольких контекстов и транзакций EF.