2009-04-23 68 views
2

我需要关于交易的LINQ到SQL中的一些帮助。以下是典型的交易布局。如果任何操作失败,则所有操作都会回滚。交易中的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对子集合进行引用。在所有操作中,我传递父引用并将子实体集作为parent.Childs获取。我在Childs Linq表中添加子记录,而不是Childs EntitySet。在操作#1之后,我做了db.submitChanges()。对于op#2,我没有在parent.Childs EntitySet中看到操作#1的插入记录,即使在db.SubmitChanges()之后 - 但我在Child Linq表中看到。有任何想法吗?

我想这样做使用LINQ to对象。 Linq to Object似乎不会在后续操作中“查看”InsertOnSubmit记录(例如:如果我在子表中插入记录,则从父项关系返回的EntitySet不会显示插入的记录)。

我能够在LINQ到实现这一目标,以SQL,但在成本重新查询整个LINQ的表。我将不得不为每个操作编写重复的代码。

任何想法?请让我知道,如果你能想到一个更简单的方法。谢谢。

+0

我不明白了 - 运行2应* *已经看到操作1的结果。操作1的结果在第一个db.SubmitChanges()后变为可见。这是不是在你的情况发生?我误解了这个问题吗? – Sander 2009-04-24 08:53:52

回答

0

这晚,但我想回答这个问题。

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

0

如果每个父表的命令datasize足够管理,我用(的linqToSqlRowType)的列表来跟踪人口和新行补充说。所以我查询了尚未提交更改的子操作列表。

此外,在Linq to sql中,也可能将linq转换为对象,您可以将外键行字段设置为尚未提交的行,并且它会自动处理任何标识字段。