TransactionScope требует включения DTC в C # MVC

Мы используем RDS (Amazon Relational Database Service) для нашей базы данных. у нас есть несколько sp, которые вызываются в transactionScope. мы настроили ExecutionStrategy для нашего DBConfig, как это

public class MpDbConfiguration : DbConfiguration
    {
        public MpDbConfiguration()
        {
            //SetExecutionStrategy(
            //    "System.Data.SqlClient", () => new MpExecutionStrategy(10, TimeSpan.FromMilliseconds(100)));

            SetExecutionStrategy("System.Data.SqlClient", () => SuspendExecutionStrategy
                ? (IDbExecutionStrategy)new DefaultExecutionStrategy()
                : new MpExecutionStrategy(10, TimeSpan.FromMilliseconds(100)));
        }
//.....
}

SuspendExecutionStrategy имеет значение True, когда у нас есть пользовательская транзакция (в соответствующей статье я использовал эту defaultStrategy: https://docs.microsoft.com/en-us/ef/ef6/fundamentals/connection-resiliency/retry-логика)

Проблема: у меня возникает эта проблема, когда я запускаю такие транзакции

   using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {

                    if (entity != null && !string.IsNullOrEmpty(entity.EmailAddress))
                    {
                        ObjectFactory.GetInstance<IBankingService>().UnRegister(RequestContext.Current, entity);
                    }

                    Data.Configuration.MpDbConfiguration.SuspendExecutionStrategy = true;
                    Context.Current.Database.ExecuteSqlCommand("DeleteAccountByEmailAddress @usertodelete",
                                                               new SqlParameter("usertodelete", emailAddress));
                    scope.Complete();
                    Data.Configuration.MpDbConfiguration.SuspendExecutionStrategy = false;
                }
//....

Этот SP - очень большая транзакция, но использует ТОЛЬКО одну базу данных. Я получаю ошибку, чтобы включить DTC. мой вопрос: ПОЧЕМУ МНЕ НУЖЕН DTC?

Базовый провайдер не удалось открыть. Доступ к сети для диспетчера распределенных транзакций (MSDTC) отключен. Включите DTC для доступа к сети в конфигурации безопасности для MSDTC с помощью инструмента администрирования служб компонентов.

На самом деле эти термины для меня довольно новы, но, основываясь на поиске, я обнаружил, что DTC используется только тогда, когда у нас есть распределенные транзакции. В нашем случае его нет.


person Sara N    schedule 01.05.2019    source источник
comment
DTC также может быть вызван при наличии нескольких параллельных (вложенных) внешних транзакций в одном контексте или когда одна внешняя транзакция обращается к нескольким источникам данных; есть ли какой-либо код, который вызывает это создание TransactionScope? UnRegister обращается к базе данных? Кроме того, если вы выполняете только одну операцию SQL - зачем использовать TransactionScope? - возможно, просто используйте обычную транзакцию - или, поскольку вы, кажется, используете хранимую процедуру, просто заставьте SP работать в атомарным способом, возможно, используя внутреннюю транзакцию (и никакой транзакции у вызывающей стороны)   -  person Marc Gravell    schedule 01.05.2019
comment
Функция @MarcGravell UnRegister - это еще один вызов внешней службы, которая использует базу данных с нашей стороны. Насколько я знаю, это не несколько источников данных.   -  person Sara N    schedule 01.05.2019
comment
@MarcGravell Насколько я понимаю, transactionScope не всегда требует включения DTC. только когда он находит несколько источников данных или соединений. Это правильно?   -  person Sara N    schedule 01.05.2019
comment
Требования здесь зависят от СУБД и конкретной версии сервера базы данных, а также от ОС клиента и версии .NET Framework, которую вы используете. возможно не использовать DTC для двух последовательных, но не одновременных подключений к одному и тому же источнику данных, но: для чего-то более сложного, как правило, потребуется DTC, а при отключении level что угодно, то даже для двух последовательных (не одновременных) соединений может потребоваться DTC   -  person Marc Gravell    schedule 01.05.2019


Ответы (1)


Решением может быть использование устаревшего типа транзакций вместо области действия транзакции. очевидно, что служба там может использовать другой контекст. Я также добавил try catch для отката транзакции в случае какого-либо исключения.

Спасибо @MarcGravell за подсказки.

   using (var dbContextTransaction = Context.Current.Database.BeginTransaction())
                {
                    try
                    {
                     //--- the code run inside the transaction 
                        Context.Current.SaveChanges();
                        dbContextTransaction.Commit();
                        return true;
                    }
                    catch (Exception ex)
                    {
                        dbContextTransaction.Rollback();
                       //....
                    }
                 }
person Sara N    schedule 20.05.2019