2016-04-26 4 views
2

В моем .NET-коде внутри транзакции базы данных (с использованием TransactionScope) я мог бы включить вложенный блок с TransactionScopeOption.Suppress, который гарантирует, что команды внутри вложенного блока будут совершены, даже если внешний блок откидывается назад. Ниже приведен пример кода:Эквивалент T-SQL .NET TransactionScopeOption.Suppress

using (TransactionScope txnScope = new TransactionScope(TransactionScopeOption.Required)) 
{ 
    db.ExecuteNonQuery(CommandType.Text, "Insert Into Business(Value) Values('Some Value')"); 

    using (TransactionScope txnLogging = new TransactionScope(TransactionScopeOption.Suppress)) 
    { 
     db.ExecuteNonQuery(CommandType.Text, "Insert Into Logging(LogMsg) Values('Log Message')"); 
     txnLogging.Complete(); 
    } 

    // Something goes wrong here. Logging is still committed 

    txnScope.Complete(); 
} 

Я пытался найти, если это может быть сделано в T-SQL. Несколько человек рекомендовали OPENROWSET, но он не выглядит очень «элегантным» для использования. Кроме того, я думаю, что это плохая идея поместить информацию о соединении в код T-SQL.

Я использовал SQL Service Broker в прошлом, но также поддерживает Transactional Messaging, что означает, что сообщение не отправляется в очередь до транзакции базы данных.

Мое требование: Хранимые процедуры нашего приложения запускаются каким-либо сторонним приложением в рамках неявной транзакции, инициированной за пределами хранимой процедуры. И я хочу, чтобы улавливать и регистрировать любые ошибки (в таблице базы данных в одной базе данных) в моих хранимых процедурах. Мне нужно повторно выбросить исключение, чтобы позволить стороннему приложению отменить транзакцию и чтобы он знал, что операция потерпела неудачу (и, следовательно, делает все, что требуется в случае сбоя).

+0

Так что ваш код .NET вызывается сторонним кодом .NET? – usr

+0

Вы просматривали переменные таблицы? – Shaneis

+0

@usr - я не знаю код стороннего приложения. Код .NET, который я опубликовал в моем вопросе, был только тем, что я хотел бы сделать то же самое в коде T-SQL. –

ответ

4

Вы можете настроить связанный с обратной связью сервер с параметром remote proc transaction Promotion, установленным на false, а затем получить к нему доступ в TSQL или использовать процедуру CLR на SQL-сервере для создания нового подключения вне транзакции и выполнения вашей работы.

Оба метода, предложенные в How to create an autonomous transaction in SQL Server 2008.

Оба метода предполагают создание новых соединений. Существует open connect item с запросом об этой функции.

+0

CLR процедура опция был на рассмотрении. Однако опция loopback Linked Server намного проще. Большое спасибо! Какие-либо заметные недостатки производительности связанного сервера? Это будет использоваться только для исключительных условий (в основном в блоках catch хранимых процедур). –

+0

Два соединения, а не одно, будут главными, о чем я могу думать, но звучит не так, как будто это будет обычная вещь. –

0

Значения в переменной таблицы существуют за пределами ROLLBACK.

Таким образом, в следующем примере все строки, которые должны были быть удалены, могут быть вставлены в сохраненную таблицу и запрошены позже благодаря комбинации OUTPUT и переменных таблицы.

-- First, create our table 
CREATE TABLE [dbo].[DateTest] ([Date_Test_Id] INT IDENTITY(1, 1), [Test_Date] datetime2(3)); 

-- Populate it with 15,000,000 rows 
-- from 1st Jan 1900 to 1st Jan 2017. 
INSERT INTO [dbo].[DateTest] ([Test_Date]) 
SELECT 
TOP (15000000) 
    DATEADD(DAY, 0, ABS(CHECKSUM(NEWID())) % 42734) 
    FROM [sys].[messages] AS [m1] 
    CROSS JOIN [sys].[messages] AS [m2]; 

BEGIN TRAN; 

BEGIN TRY 

    DECLARE @logger TABLE ([Date_Test_Id] INT, [Test_Date] DATETIME); 

    -- Delete every 1000 row 
    DELETE FROM [dbo].[DateTest] 
    OUTPUT deleted.Date_Test_Id, deleted.Test_Date INTO @logger 
    WHERE [Date_Test_Id] % 1000 = 0; 

    -- Make it fail 
    SELECT 1/0 

    -- So this will never happen 
    COMMIT TRANSACTION; 

END TRY 
BEGIN CATCH 

    ROLLBACK TRAN 
    SELECT * INTO dbo.logger FROM @logger; 

END CATCH; 

SELECT * FROM dbo.logger; 

DROP TABLE dbo.logger; 
+0

В вопросе говорится, что «стороннее приложение» откатывает транзакцию. Откат не относится к самому процессу (хотя это было бы лучшим решением, если это необязательно, когда это происходит) –

 Смежные вопросы

  • Нет связанных вопросов^_^