2011-08-08 78 views
7

我該如何執行相同的操作? My understanding is that this is impossible with TransactionScopes但我想完成一些其他方式的等價物:.NET中的嵌套事務

業務邏輯類:

public bool Bar() 
{ 
    try 
    { 
    using (var tsWork = new TransactionScope()) 
    { 
     ComplicatedDataImportCode(somedata); 
     FlagRecordInDatabaseAsImported(); // this is the same record that's modified in the catch 
     tsWork.Complete(); 
     return true; 
    } 
    catch (DuplicateDataException err) 
    { 
     // if we got here, the above transaction should have rolled back, 
     // so take that same record in the database and update it to "Duplicate". 
     FlagSameRecordInDatabaseAsDuplicate(err.Message); 
    } 

    return false; 
} 

現在這工作正常,直到我封裝了所有該交易的內部(可能是集成測試我想在執行斷言後回滾)。

簡單的測試來證明我的觀點:

public void CanTest() 
{ 
    // Arrange 
    var foo = new Foo(); 

    using (var ts = new TransactionScope()) 
    { 
    // Act 
    var success = foo.Bar(); 

    // Assert 
    if (success) 
    { 
     Assert.That(SomethingThatTestsThatTheDataWasImported); 
    } 
    else 
    { 
     Assert.That(SomethingThatTestsThatTheRecordWasMarkedAsDuplicate); 
    } 

    // Now that we have been able to perform our Asserts, rollback. 

    } 
} 

最終,在Foo.Bar()代碼可以被修改但以適應解決方案,在ComplicatedDataImportCode()代碼不能修改這個解決方案,並因此我真的需要確保在故障情況下正確回滾。

根據我在本問題開頭引用的帖子,我明白TransactionScopes不能用來做這件事。我在這裏使用了TransactionScopes來表明我想要做什麼,並且正在尋找實現此功能的最佳替代方法。

回答

2

是不是這樣,這必須由您正在使用的DBMS支持?

SQL Server並不真正支持嵌套事務,但是,對於SQL Server,您可以使用savepoints

An article我已經寫了幾年前在我的博客。

+1

SQL Server支持嵌套事務,它只是第一個'ROLLBACK'殺死所有級別。 'COMMIT'儘管嵌套。 – Kratz

+0

嗯,也許我錯誤地理解SQL Server支持這個。我想了解更多。閱讀你的鏈接。 +1現在... – Jaxidian

+0

@Kratz:您的評論正是我的問題。我想'ROLLBACK'只回滾那個特定的「內部事務」而不是整個事情。 – Jaxidian

1

如果你能得到有效的數據庫連接是ComplicatedDataImportCode使用的保持,你應該只需要運行該連接上一個BEGIN TRANROLLBACK TRAN

+0

雖然這不允許部分回滾。回滾推翻了整個交易,這就是問題所在。因此,如果我按照您的說法進行操作,那麼當執行該回滾時,我對'FlagSameRecordInDatabaseAsDuplicate'的調用將不起作用,因爲它在我的CanTest方法調用時位於同一個事務中。 – Jaxidian