Linq to sql multiple data context in same transaction

岁酱吖の 提交于 2019-11-28 12:43:11

问题


I am working on a project Where I have multiple reposetories to fetch data from differnt tables. All my repositories are independent, they create new dataContext, Add row to table and apply submit changes command. Now if in my service, there is a situation where I have to insert data into multiple tables, but it should happen in one transaction. I can achieve that using TrnasctionScope stuff, but thats needs same dataContext. As I am using StrucutreMap to create my objects, I cant get same data context, so my transaction fails.

Here is how my objects are.

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;
     }
}

Now in my Service layer I have call them as

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();   
            }

  }
}

How will I pass same data context to two differnt repositories. I option, I thought was creating one overloaded method in each repository which Accepts IDataContext parameter as given below.

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;
     }
}

and in my service layer, I would implement it as

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();   
            }

  }
}

Second thought I have is, if somehow I can configure DataContext to return same connection when I call GetContext method. so all repositories will use same connection. But I feel that will keep the connection alive all the time. I want this connection to available during the time of this SaveAll method only.

Your help will be appritiated. Thanks in advance.

Cheers Parminder


回答1:


TransactionScope can be used with multiple DataContexts, but as soon as more than one connection is involved the transaction is escalated to a MSDTC/XA/distributed transaction. For that to work you need to have MSDTC running on both the system where you code runs and on the database server.

Alternatively, you can avoid escalation to a distributed transaction if you create an explicit connection within the transactionscope and pass that to your datacontexts; that way the TransactionScope will not escalate to a distributed transaction, and won't rely on MSDTC...



来源:https://stackoverflow.com/questions/1591822/linq-to-sql-multiple-data-context-in-same-transaction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!