在哪里可以找到信息或如何在BackgroundWorker线程中处理SQL Server事务?我的理解是,不应在“DoWork”事件中设置错误处理,并且错误在内部处理并传递给“RunWorkerCompleted”。
我目前正在使用SubSonic作为我的DAL,并通过BackGroundWorder线程传递一些冗长的插入和更新。我遇到的问题是,当出现故障时,没有任何东西可以回滚。我决定使用事务管理器,但无法找到有关使用BackgroundWorker线程的事务的信息。
答案 0 :(得分:1)
使用TransactionScope进行交易非常简单。
创建一个新的TransactionScope(在使用块中可以解决)
创建一个新的Sql连接(如果你这样做,那么它将不起作用)
运行一些crud操作
完成交易
???
PROFIT !!!
在亚音速方面,这是你必须要做的事情:
using (var ts = new TransactionScope())
using (new SubSonic.SharedDbConnectionScope())
{
DoSomethingWithYourData();
ts.Complete();
}
这就是后台发生的事情:
如果您创建新的TransactionScope,则会将静态属性Transaction.Current设置为您的事务。现在,如果您创建一个新的DbConnection,则连接本身会查看Transaction.Current是否为null并且是否为TransactionCompleted事件。
如果在放置Connection之前调用ts.Complete(),则提交事务,否则将回滚事务,并在TransactionScopes Dispose()方法中抛出异常。
SubSonic本身将为您执行的每个语句创建一个新的连接(没有错误,它来自设计)但对交易不实用。这就是SharedDbConnectionScope()存在的原因。它与TransactionScope的工作方式类似(如果新的AutomaticConnectionScope检测到当前有SharedDbConnectionScope(),则会使用它的连接。否则将创建一个新连接。
顺便说一句,using
语法只不过是:
var obj = new ObjectThatImplementsIDisposable();
try
{
}
finally
{
obj.Dispose();
}
长话短说:如果您在线程或BackgroundWorker中运行它,它不会影响您的事务。但是,你应该记住,如果你使用SharedDbConnecionScope(),即使来自其他线程的查询也会使用它们,我不认为SqlClient库是线程安全的(但我可能是错的,但MySqlClient肯定不是。
Conculstion:我会切换到TransactionScope,因为它易于使用,灵活,通用(如果你决定有一天用你的应用程序切换到mysql或oracle,你不必担心)
首先阅读问题的第一部分: - 我认为让BackGroundWorker的DoWork方法抛出异常是一个糟糕的设计。但你可以使用这种方法:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
ExecuteATransaction()
}
catch (Exception ex)
{
RollBackTransaction();
e.Result = ex;
}
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Result && e.Result.GetType() == typeof(Exception))
throw ((Exception)e.Result);
else
Console.WriteLine("Everything went better than expected ;-)");
}