2009-05-23 2 views
4

Если вызов sql завершается неудачно, скажем, что тайм-аут из-за тупика, транзакция может превратиться в транзакцию с зомби - я думаю, что либо мой код, либо код фрейма делает откат. SqlTransaction не является нулевым, но это зомби может вызвать ошибку, если вы попытаетесь выполнить Rollback(). Я не могу найти свойство .IsZombie.Есть ли способ проверить потенциальную транзакцию зомби, чтобы увидеть, можно ли ее откат?

// Make sure the transaction is not null 
if (transaction != null) 
{ 
    //TODO: Is there a way to test a transaction to see if it can be rolled back? 
    transaction.Rollback(); 
} 

ответ

2

Вы можете попробовать использовать класс TransactionScope из .NET 2.0 в System.Transactions пространство имен. Этот класс позволяет указать тайм-аут, после которого транзакция будет автоматически отменена и откат. ADO.NET в .NET 2.0+ является TransactionScope известно, и будет автоматически зарегистрировать DbTransaction в объеме, если он присутствует в то время, база данных называется:

public void DoSomething() 
{ 
    using (TransactionScope scope = new TransactionScope(TransactionScopeOptions.Required, TimeSpan.FromSeconds(60))) 
    { 
     MyDac(); 

     scope.Complete(); // If timeout occurrs, this line is never hit, scope is disposed, which causes rollback if Complete() was not called 
    } 
} 

public class MyDac() 
{ 

    using (SqlConnection ...) 
    { 
     using (SqlCommand ...) 
     { 
      // Do something with ADO.NET here...it will autoenroll if a transaction scope is present 
     } 
    } 
} 

TransactionScope создает System.Transactions.Transaction внутри, который по умолчанию разрешает легкие транзакции SQL Server, если задействован только один сервер. Если в транзакции задействовано несколько серверов или распределенных менеджеров ресурсов, транзакция, обернутая TransactionScope, будет переведена на распределенную транзакцию, для которой требуется, чтобы MSDTC координировал, что может усложнить использование TransactionScope. Если все ваши транзакции являются легкими, TransactionScope может предложить много преимуществ по сравнению с управлением транзакциями db вручную.

0

Вы можете рассмотреть возможность размещения вашего кода обработки внутри базы данных транзакции, где вы можете испытать для @@ ERROR = 1205, чтобы определить, если ваш запрос был жертвой тупика, в этом случае вы можете повторить или ROLLBACK. Разрешить клиентским приложениям создавать и управлять транзакциями немного рискованно и лучше избегать, если это возможно.

Надеется, что это помогает,

Биллу

+0

Желательно, чтобы я мог легко переключиться на транзакции на стороне сервера. У меня есть 500 хранимых процедур в паре с уровнем доступа к данным ADO.NET. Большинство транзакционных вызовов были добавлены в качестве шаблона. – MatthewMartin

1

Прошу прощения, но я не могу не согласиться. Клиентские транзакции - это то, что позволяет иметь атомную операцию бизнес-процесса. Если вы хотите переместить все транзакционные операции в БД, вы неизменно перемещаете в нее бизнес-логику. Это подход, но крайне не рекомендуется, если вы будете использовать немного сложную логику для своей программы. Имея whiles/for/foreachs, строковые проверки и другие тривиальные операции действительно тяжелы, чтобы переместиться в DB (а иногда и даже невозможно). Подсказка тупика, однако, представляется весьма полезной и обеспечивает дополнительный контроль над клиентским приложением (что, на мой взгляд, является лучшим способом).

Cheers

+2

Добро пожаловать в стек над потоком, интересный момент и в основном согласен. Я не уверен, на кого вы отвечаете, конвенция на SO - это «ответ» - все идет в ответах и ​​«обсуждении» - все идет в комментариях с @name, чтобы прояснить получателя. – MatthewMartin