Linq在同一事务中sql多个数据上下文

时间:2009-10-20 00:18:54

标签: linq linq-to-sql transactionscope

我正在开发一个项目,其中有多个reposetories来从中获取数据 不同的表格。我的所有存储库都是独立的,它们创建新的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方法期间可用。

您的帮助将受到批准。提前致谢。

干杯 成员Parminder

1 个答案:

答案 0 :(得分:6)

TransactionScope可以与多个DataContexts一起使用,但只要涉及多个连接,事务就会升级到MSDTC / XA /分布式事务。为此,您需要在运行代码的系统和数据库服务器上运行MSDTC。

或者,如果在transactionscope中创建显式连接并将其传递给datacontexts,则可以避免升级到分布式事务;这样,TransactionScope不会升级到分布式事务,也不会依赖MSDTC ...