我需要從外部數據源向我的數據庫執行數據導入。由於需要下載大量數據,因此導入執行的時間很長,我需要將有關當前導入狀態的定期更新保存到數據庫(供用戶使用)。交易操作同時與非交易操作混合
假設我有兩個表:Import
(存儲導入數據)和Status
(導入狀態監視表)。
數據導入代碼:
public class Importer
{
public delegate void ImportHandler(string item);
public event ImportHandler ImportStarted;
public void OnStart(string item)
{
ImportStarted(item);
}
public void Execute(string[] items)
{
foreach (var item in items)
{
OnStart(item);
PersistImportedData(Download(item));
}
}
private void PersistImportedData(object data)
{
using (var connection = new SqlConnection()){ /*saving imported data*/ }
}
}
起動代碼 - 用於調用導入任務和更新其狀態:
public class Starter
{
public void Process(string[] items)
{
var importer = new Importer();
importer.ImportStarted += UpdateImportState;
importer.Execute(items);
}
private void UpdateImportState(string item)
{
using (var connection = new SqlConnection()){ /*status updates*/ }
}
}
現在一切工作正常。正在執行導入,並且隨着導入的繼續,用戶正在獲取狀態更新(從Status
表中)。
發生該問題是因爲此類邏輯不安全。我必須確定,進口是一項原子操作。我不想部分下載和保存數據。我使用的交易方式爲這個(我包裹importer.Execute
與TransactionScope
)的解決方案:
importer.ImportStarted += UpdateImportState;
using (var scope = new TransactionScope())
{
importer.Execute(items);
scope.Complete();
}
現在我已經安全 - 回滾例如發生在進程中止的情況下。
我現在面臨着不同的問題 - 我想解決的問題。我需要狀態更新信息才能顯示,但Status
表不受更新的影響,而事務尚未完成。即使我嘗試使用RequiresNew
選項來創建單獨的事務(不是環境事務),也沒有任何更改。 Execute
函數創建它自己的數據庫連接,並且UpdateImportState
也一樣。連接不共享。我不知道爲什麼State
表不會受到影響,即使TransactionScope
僅涵蓋與Import
表連接的邏輯。
如何保留一致的導入並允許定期狀態更新?
這【答案】(http://stackoverflow.com/a/2886326/1402923)在TransactionScope的行爲可能是有用的。 – RobH