Хобрук: Ваш путь к мастерству в программировании

Несколько баз данных (datacontext) на одном сервере без MS DTC

Я использую EF5.0 с SQL server 2008. У меня две базы данных на одном экземпляре сервера. Мне нужно обновить таблицы в обеих базах данных, и я хочу, чтобы они были одной и той же транзакцией. Поэтому я использовал TransactionScope. Ниже приведен код -

public void Save()
{
        var MSObjectContext = ((IObjectContextAdapter)MSDataContext).ObjectContext;
        var AWObjectContext = ((IObjectContextAdapter)AwContext).ObjectContext;

        using (var scope = new TransactionScope(TransactionScopeOption.Required,
                                             new TransactionOptions
                                                 {
                                                     IsolationLevel = IsolationLevel.ReadUncommitted
                                                 }))
        {               
            MSObjectContext.SaveChanges(SaveOptions.DetectChangesBeforeSave);
            AWObjectContext.SaveChanges(SaveOptions.DetectChangesBeforeSave);

            scope.Complete();
        }
    }

Когда я использую приведенный выше код, транзакция повышается до DTC. После поиска в Интернете я обнаружил, что это происходит из-за двух разных строк / соединений. Но я не понимаю, что если я пишу хранимую процедуру в одной базе данных, которая обновляет таблицу в другой базе данных (на том же сервере), DTC не требуется. Тогда почему EF или TransactionScope продвигают это в DTC? Есть ли другой способ решения этой проблемы?

пожалуйста, порекомендуйте

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

Сай


Ответы:


1

Используя простой DbConnections, вы можете предотвратить эскалацию DTC для нескольких баз данных на одном сервере, используя одну и ту же строку подключения (с любой базой данных, которая вам нравится) и вручную изменить базу данных в открытом объекте подключения следующим образом:

using (var tx = new TransactionScope())
{
    using (var conn = new SqlConnection(connectStr))
    {
        conn.Open();
        new SqlCommand("INSERT INTO atest VALUES (1)", conn).ExecuteNonQuery();
    }
    using (var conn = new SqlConnection(connectStr))
    {
        conn.Open();
        conn.ChangeDatabase("OtherDB");
        new SqlCommand("INSERT INTO btest VALUES (2)", conn).ExecuteNonQuery();
    }
    tx.Complete();
}

Это не перейдет в DTC, но будет, если вы использовали другие значения для connectStr.

Я не знаком с EF и тем, как он управляет соединениями и контекстами, но, используя приведенное выше понимание, вы можете избежать эскалации DTC, выполнив conn.ChangeDatabase(..), а затем создав свой контекст, например _ 5_.

Но обратите внимание, что даже с общей строкой подключения, как только у вас будет открыто более одного подключения одновременно, DTC будет задействован, как в этом модифицированном примере:

using (var tx = new TransactionScope())
{
    using (var conn = new SqlConnection(mssqldb))
    {
        conn.Open();
        new SqlCommand("INSERT INTO atest VALUES (1)", conn).ExecuteNonQuery();
        using (var conn2 = new SqlConnection(mssqldb))
        {
            conn2.Open();
            conn2.ChangeDatabase("otherdatabase");
            new SqlCommand("INSERT INTO btest VALUES (2)", conn2).ExecuteNonQuery();
        }
    }
    tx.Complete();
}
11.10.2013
  • Я хочу совершать транзакции на двух совершенно разных базах данных на одном сервере в рамках одной области транзакции. Я мог бы сделать это с помощью хранимых процедур, но не с помощью EF. Спасибо за ответ. 11.10.2013
  • Мой ответ действительно показывает, как использовать TransactionScope для этого, не прибегая к хранимым процедурам. Неявное tx.Dispose(), которое появляется после строки tx.Complete(), фиксирует одну транзакцию, которая включает оба INSERT, в две разные базы данных. Как уже упоминалось, с EF есть способы предоставить соединения, в которых вы вручную вызываете ChangeDatabase(), но в зависимости от вашей кодовой базы это может привести к более тесно связанному коду (в то время как суть TransactionScoep заключается в разделении кода), это можете сказать только вы. 15.10.2013
  • Я не думаю, что могу использовать ChangeDatabase (), поскольку я использую подход Databasefirst, а мой dbcontext жестко привязан к объектам. Если я изменю строку подключения во время выполнения на совершенно другую базу данных, это вызовет ошибку. 15.10.2013
  • calling ChangeDatabase() и изменение connectionString во время выполнения - это разные вещи. Но если вы сами не создадите DbContext, вам действительно может не повезти. 16.10.2013
  • Просто хочу сказать, что это чрезвычайно полезный ответ, который я пока нашел только здесь. Я бы отметил, что это правильно, если бы мог! 12.02.2015
  • @Josh Sai спрашивал, как это сделать в EF, и, не зная EF, я не могу сказать, может ли мой общий рецепт быть реализован в EF. Так что, возможно, это не ответ для него. Но я рад, что это помогло вам. 13.02.2015
  • Новые материалы

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

    Управление состоянием в микрофронтендах
    Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..