如何将SubSonic事务与父子表一起使用

时间:2009-09-03 18:28:14

标签: c# subsonic transactions

我有2个表(为简单起见,许多字段已删除)

tblOrder - OrderId - 订购日期 - UserId

tblOrderDetail - OrderDetailId - OrderId - ProductId - Qantity

我继续创建我的对象,我希望在一个事务中将所有内容保存在内存中,因为如果订单细节中的某些内容失败,我不希望保存订单。我使用以下代码,但我不明白如何在一次交易中正确地执行此操作。

Order newOrder = new Order();
OrderDetailCollection newOrderDetails = new OrderDetailCollection();
OrderDetail newOrderDetail;

newOrder.OrderDate = DateTime.Now();
newOrder.UserId = 1;

newOrderDetail = new OrderDetail();
// newOrderDetail.OrderId = newOrder.OrderId; // Can't do that yet, newOrder is not saved and OrderId is Null.
newOrderDetail.ProductId = 1;
newOrderDetail.Quantity = 25;

newOrderDetails.Add(newOrderDetail);

newOrderDetail = new OrderDetail();
// newOrderDetail.OrderId = newOrder.OrderId; // Can't do that yet, newOrder is not saved and OrderId is Null.
newOrderDetail.ProductId = 1;
newOrderDetail.Quantity = 25;

newOrderDetails.Add(newOrderDetail);

//只有两个用于测试目的。

现在我可以轻松地做到这一点

using (System.Transactions.TransactionScope ts = new TransactionScope()) {    
   using (SharedDbConnectionScope scs = new SharedDbConnectionScope()) { 
      try {
         newOrder.Save();

         foreach(OrderDetail anOrderDetail in newOrderDetails) {
            anOrderDetail.OrderId = newOrder.OrderId;
         }

         newOrderDetails.BatchSave();

         ts.Complete();
      }        
      catch (Exception ex) {
         //Do stuff with exception or throw it to caller
      }
   }
}

但这似乎不是最优雅的解决方案:

  1. 因为我必须遍历表中的每个项目来设置ID,然后保存批次。

  2. 因为出错,我在数据库中丢失了一个ID。 (即,如果发生错误,首先保存,OrderId = 1将丢失,下一个OrderId将为2)

  3. 不适用于具有其他子表的非常大的事务。在这个解决方案中,我使用Order表和Order Detail表构建了一个例子,但在我的实际应用程序中,OrderDetail OrderDetailCreditMember和OrderDetailCreditCompany下还有另外两个级别,在任何购买时,一小笔金额记入会员和公司(多行)所以我最终得到一个包含1个订单的树,其中包含2个订单详细信息,每个订单详细信息包含2个成员信用额度和3个公司信用额度。

  4. 所以有人有更好的方法来做到这一点。

1 个答案:

答案 0 :(得分:2)

老实说,我认为你可能会在这里过早优化。

  1. 因为我必须遍历表中的每个项目以设置ID,然后保存批次。
  2. 你在内存中进行迭代,你的事务中只有两个SQL调用,对我来说似乎效率不高。

    1. 因为出错,我在数据库中丢失了一个ID。 (即首次保存,如果发生错误,OrderId = 1将丢失,下一个OrderId将为2)
    2. 这真的是一个问题吗,你经常会发生错误的发生,我假设你在尝试保存它们之前验证了你的对象,所以你真的应该很少得到错误(例如可以连接到db)所以我不相信这是一个问题。如果你遇到很多错误,那就是需要单独解决的问题。

      1. 不适用于具有其他子表的非常大的事务。在这个解决方案中,我使用Order表和Order Detail表构建了一个例子,但在我的实际应用程序中,OrderDetail OrderDetailCreditMember和OrderDetailCreditCompany下还有另外两个级别,在任何购买时,一小笔金额记入会员和公司(多行)所以我最终可能会得到一个包含1个订单的树,其中包含2个订单详细信息,每个订单详细信息包含2个成员信用和3个公司信用。
      2. 是的,这里可能存在扩展问题,但你在谈论1 x 2 x 2 x 3 = 12次迭代的内存循环和3次SQL调用。除非你经常发生这种情况,否则这不应该是一个太大的问题。您多久预期会调用此方法?