Linq для sql нескольких контекстов данных в одной транзакции

Я работаю над проектом, в котором у меня есть несколько репозиториев для извлечения данных из разных таблиц. Все мои репозитории независимы, они создают новый dataContext, добавляют строку в таблицу и применяют команду отправки изменений. Теперь, если в моем сервисе есть ситуация, когда мне нужно вставить данные в несколько таблиц, но это должно произойти за одну транзакцию. Я могу добиться этого с помощью TrnasctionScope, но для этого нужен тот же dataContext. Поскольку я использую StrucutreMap для создания своих объектов, я не могу получить тот же контекст данных, поэтому моя транзакция не выполняется.

Вот каковы мои объекты.

interface IConnection
{
 MyDataContext GetContext();
}

public class Connection : IConnection
{

   public MyDataContext GetContext()
   {
    return new MyDataContext();
   }

} 

interface IRepositryA
{
  int SaveDataA(objectA a);
}

public class RepositoryA : IRepositryA
{
     public int SaveDataA(objectA a)
     {
        var context = objectFactory.GetInstance<IConnection>().GetContext();   
        context.TableA.InsertOnSubmit(a);
        context.SubmitChanges();

        return a.ID;
     }
}

interface IRepositryB
{
   int SaveDataA(objectB b);
}

public class RepositoryA : IRepositryB
{
     public int SaveDataB(objectB b)
     {

        var context = objectFactory.GetInstance<IConnection>().GetContext();   
        context.TableB.InsertOnSubmit(b);
        context.SubmitChanges();
        return b.ID;
     }
}

Теперь в моем сервисном слое я назвал их как

public MyServiceClass ()
 {
 public SaveAll(ObjectA a, ObjectB b)
 {

             using (TransactionScope trn);
            {
                ObjectFactory.GetInstance<IRepositryA>().SaveDataA(a);
                b.FkeyID = a.ID;
                ObjectFactory.GetInstance<IRepositryB>().SaveDataB(b);

                trn.complete();   
            }

  }
}

Как передать один и тот же контекст данных в два разных репозитория. Я вариант, я думал, что создавал один перегруженный метод в каждом репозитории, который принимает параметр IDataContext, как указано ниже.

interface IRepositryA
{
  int SaveDataA(objectA a);
  int SaveDataA(IConnection connection, objectA a);

}

public class RepositoryA : IRepositryA
{
     public int SaveDataA(objectA a)
     {
        var connection = objectFactory.GetInstance<IConnection>();   

        return SaveData(connection, a);
     }

     public int SaveDataA(IConnection connection, objectA a)
     {
        var context = connection.GetContext();   
        context.TableA.InsertOnSubmit(a);
        context.SubmitChanges();

        return a.ID;
     }

}

interface IRepositryB
{
   int SaveDataA(objectB b);
   int SaveDataA(IConnection connection, objectB b);

}

public class RepositoryA : IRepositryB
{
     public int SaveDataB(objectB b)
     {
        var connection = objectFactory.GetInstance<IConnection>();   
        return SaveData(connection, b);
     }

     public int SaveDataA(IConnection connection, objectB b)
     {
        var context = connection.GetContext();   
        context.TableB.InsertOnSubmit(b);
        context.SubmitChanges();

        return b.ID;
     }
}

и на моем уровне обслуживания я бы реализовал его как

public MyServiceClass ()
 {
 public SaveAll(ObjectA a, ObjectB b)
 {
            IConnection connection= ObjectFactory.GetInstance<IConnection>();
            using (TransactionScope trn);
            {
                ObjectFactory.GetInstance<IRepositryA>().SaveDataA(connection,a);
                b.FkeyID = a.ID;
                ObjectFactory.GetInstance<IRepositryB>().SaveDataB(connection,b);

                trn.complete();   
            }

  }
}

Вторая мысль, которая у меня есть, заключается в том, что если я каким-то образом могу настроить DataContext для возврата того же соединения, когда я вызываю метод GetContext. поэтому все репозитории будут использовать одно и то же соединение. Но я чувствую, что это будет поддерживать связь все время. Я хочу, чтобы это соединение было доступно только во время использования этого метода SaveAll.

Ваша помощь будет оценена. Заранее спасибо.

Ура, Парминдер


person Parminder    schedule 20.10.2009    source источник
comment
Почему вы считаете, что TransactionScope работает только с одним DataContext?   -  person Pavel Minaev    schedule 20.10.2009
comment
Я пробовал с другим контекстом, и это не удалось.   -  person Parminder    schedule 20.10.2009


Ответы (1)


TransactionScope можно использовать с несколькими DataContexts, но как только задействовано более одного соединения, транзакция переходит в MSDTC / XA / распределенную транзакцию. Чтобы это работало, вам необходимо, чтобы MSDTC работал как в системе, в которой выполняется код, так и на сервере базы данных.

В качестве альтернативы вы можете избежать эскалации до распределенной транзакции, если вы создадите явное соединение в области транзакции и передадите его своим текстам данных; таким образом TransactionScope не перерастет в распределенную транзакцию и не будет полагаться на MSDTC ...

person KristoferA    schedule 20.10.2009
comment
как система, в которой выполняется код, так и на сервере базы данных. Только что обратил на это мое внимание ура +1 - person Andrew; 23.11.2009
comment
Избегать MSDTC - всегда лучший вариант! - person Gabriel GM; 05.09.2014