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

发布于 2024-08-08 11:22:17 字数 3444 浏览 6 评论 0原文

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

我们将感谢您的帮助。提前致谢。

干杯 帕明德

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

那一片橙海, 2024-08-15 11:22:17

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

或者,如果您在事务范围内创建显式连接并将其传递到数据上下文,则可以避免升级为分布式事务;这样 TransactionScope 就不会升级为分布式事务,并且不会依赖 MSDTC...

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文