【问题标题】:Transactions in LINQ to SQLLINQ to SQL 中的事务
【发布时间】:2013-07-11 15:23:31
【问题描述】:

我需要一些有关 Linq to sql 事务的帮助。以下是典型的交易布局。如果任何操作失败,则所有操作都将回滚。

mainTransaction (tScope)
     Operation 1 changes
     db.submitChanges()

     Operation 2 changes
     db.submitChanges()    
     ...

     catch(TransactionException ex)
         'rollback mainTransaction

     tScope.complete()

但是,我希望有一个场景,操作 2 应该能够看到操作 1 的更改,如果任何操作失败,则所有先前的操作都将回滚.

我可以想到 Linq to Sql 中的嵌套事务,但也许有更好的方法。我还没有尝试过嵌套事务的方法。

mainTransaction
    childTransaction #1 
        child 1 changes

    childTransaction #2 changes
        should see child 1 changes
        child 2 changes

    childTransaction #3 changes
        should see child 1 changes
        should see child 2 changes
        child #3 changes

catch(TransactionException ex)
    'rollback child 1
    'rollback child 2
    ...
tScope.complete()

更新:假设我们有父子关系。父级将引用子集合作为 parent.Childs EntitySet。在所有操作中,我传递父引用并将子 EntitySet 作为 parent.Childs 获取。我在 Childs Linq 表中添加子记录,而不是 Childs EntitySet。在 op# 1 之后,我执行 db.submitChanges()。对于 op# 2,即使在 db.SubmitChanges() 之后,我也没有在 parent.Childs EntitySet 中看到 op# 1 的插入记录——但是,我在 Child Linq 表中看到了。有什么想法吗?

我想使用 Linq to Object 来做到这一点。 Linq to Object 在后续操作中似乎没有“看到” InsertOnSubmit 记录(例如:如果我在子表中插入一条记录,则从父关系返回的 EntitySet 不会显示插入的记录)。

我能够在 Linq to SQL 中实现这一点,但代价是重新查询整个 Linq 表。我必须为每个操作编写重复的代码。

有什么想法吗?如果您能想到更简单的方法,请告诉我。谢谢。

【问题讨论】:

  • 我不明白 - 操作 2 应该已经看到操作 1 的结果。操作 1 的结果在第一个 db.SubmitChanges() 之后变得可见。在你的情况下没有发生这种情况吗?我误解了这个问题吗?
  • 我用斜体示例更新了问题并将其标记为“更新:”。
  • 我只使用一个事务并跟踪要插入到列表中的所有记录。

标签: linq transactions


【解决方案1】:

如果每个父表的数据大小足够易于管理,我使用一个列表(linqToSqlRowType)来跟踪人口和添加的新行。所以我在列表中查询了尚未提交更改的子操作。

在 Linq to sql 中也可能 linq to objects,您可以将外键行字段设置为尚未提交的行,它会自动处理任何身份字段。

【讨论】:

    【解决方案2】:

    已经很晚了,但我想回答这个问题。

    选项 1:使用TransactionScope。我不喜欢这个。

    // if an exception is thrown, ts.Complete() is not called causing rollback
    using (TransactionScope ts = new TransactionScope())
    {
        // operation 1 changes //
        var items = db.Items.ToList();
        var itemToFind = items.Where(somePredicate);
        db.Items.InsertOnSubmit(item1);
        db.Items.InsertOnSubmit(item2);
        db.SubmitChanges();
    
        // operation 2 changes //
        // re-query the table(s) again
        var items = db.Items.ToList();
        var itemToFind = items.Where(somePredicate);
        db.Items.InsertOnSubmit(item3);
        db.SubmitChanges()
    
        ts.Complete();
    }
    

    选项 2:查看context.GetChangeSet()InsertsUpdatesDeletes

    // operation 1 changes //
    var items = db.Items.ToList();
    var itemToFind = items.Where(somePredicate);
    db.Items.InsertOnSubmit(item1);
    db.Items.InsertOnSubmit(item2);
    // do not submit changes here
    
    // operation 2 changes //
    // look in the ChangeSet
    var itemToFind = items.Where(somePredicate);
    if (itemToFind = null)
        itemToFind = db.GetChangeSet().Inserts.OfType<Item>().Where(somePredicate);
    db.Items.InsertOnSubmit(item3);
    db.SubmitChanges()    
    
    // submit changes when all done
    db.SubmitChanges();
    

    选项 3:维护一个单独的列表并查看它(类似于选项 2)。

    // operation 1 changes //
    var items = db.Items.ToList();
    var itemToFind = items.Where(somePredicate);
    db.Items.InsertOnSubmit(item1);
    db.Items.InsertOnSubmit(item2);
    customList.Add(item1);
    customList.Add(item2);
    // do not submit changes here
    
    // operation 2 changes //
    // look in the ChangeSet
    var itemToFind = items.Where(somePredicate);
    if (itemToFind = null)
        itemToFind = customList.Where(somePredicate);
    db.Items.InsertOnSubmit(item3);
    db.SubmitChanges()    
    
    // submit changes when all done
    db.SubmitChanges();
    

    我根据情况使用了选项 2 和 3,但回避了选项 1。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 2021-09-10
      • 2010-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多