Linq to sql множество контекст на данни в една и съща транзакция

Работя върху проект, където имам множество хранилища за извличане на данни от различни таблици. Всички мои хранилища са независими, те създават нов dataContext, добавят ред към таблицата и прилагат команда за изпращане на промени. Сега, ако в моята услуга има ситуация, в която трябва да вмъкна данни в множество таблици, но това трябва да се случи в една транзакция. Мога да постигна това с помощта на неща на TrnasctionScope, но това се нуждае от същия контекст на данни. Тъй като използвам 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();   
            }

  }
}

Как ще предам един и същ контекст на данни в две различни хранилища. I вариант, мислех, че създавам един претоварен метод във всяко хранилище, което приема параметър 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