.NET BackgroundWorker и SQLTransactions - PullRequest
       7

.NET BackgroundWorker и SQLTransactions

1 голос
/ 21 октября 2010

Где я могу найти информацию или как я могу обрабатывать транзакции SQL Server в потоке BackgroundWorker? Насколько я понимаю, обработку ошибок не следует устанавливать в событии «DoWork», а ошибка обрабатывается внутренне и передается в «RunWorkerCompleted».

В настоящее время я использую SubSonic в качестве моего DAL и передаю некоторые длинные вставки и обновления через поток BackGroundWorder. У меня проблема в том, что когда что-то не получается, ничего не происходит. Я принимал решение об использовании транзакции, но не смог найти информацию об использовании транзакций с потоком BackgroundWorker.

1 Ответ

1 голос
/ 22 октября 2010

Транзакция с TransactionScope довольно проста.

  1. Создать новый TransactionScope (предпочтительно в блоке использования)

  2. Создать новое соединение Sql(если вы сделаете это наоборот, это не сработает)

  3. Выполнить некоторые грубые операции

  4. Завершить транзакцию

  5. ???

  6. ПРИБЫЛЬ !!!

С точки зрения дозвуковых это то, что вы должныdo:

using (var ts = new TransactionScope())
using (new SubSonic.SharedDbConnectionScope())
{

    DoSomethingWithYourData();

    ts.Complete();
}

Вот что происходит в фоновом режиме:

Если вы создаете новый TransactionScope, статическое свойство Transaction.Current устанавливается для вашей транзакции.Теперь, если вы создаете новое DbConnection, сами соединения проверяют, имеет ли Transaction.Current значение NULL и записывает событие TransactionCompleted.

Если вы вызываете ts.Complete () до удаления Соединения, транзакцияВ противном случае он будет откатан, исключение - это бросить в методе TransactionScopes Dispose ().

SubSonic сам создаст новое соединение для каждого выполняемого вами оператора (без ошибок, это по дизайну), но не практично дляСделки.Это причина, по которой существует SharedDbConnectionScope ().Он работает аналогично TransactionScope (если новый AutomaticConnectionScope обнаруживает наличие текущего SharedDbConnectionScope (), его соединение будет использовано. В противном случае будет создано новое соединение.

Кстати, синтаксис usingничего кроме этого:

var obj = new ObjectThatImplementsIDisposable();
try
{

}
finally
{
    obj.Dispose();
}

Короче говоря: это не повлияет на вашу транзакцию, если вы запустите ее в потоке или BackgroundWorker. Однако вы должны помнить, что, если вы используете SharedDbConnecionScope ()даже запросы из других потоков будут использовать их, и я не думаю, что библиотека SqlClient является поточно-безопасной (но я могу ошибаться, но MySqlClient определенно нет.

Заключение: я бы переключился на TransactionScope, потому что этопрост в использовании, гибок, универсален (и если вы когда-нибудь решите переключиться на MySQL или Oracle с вашим приложением, вам не о чем беспокоиться)

Читая первую часть вопроса: - Я думаю,нехорошо, если метод DoWork BackGroundWorker's выдает исключение, но вы можете использовать этоподход:

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 ;-)");
}
...