यह त्रुटि तब होती है जब आप किसी लेन-देन के अंदर एक कोशिश/पकड़ ब्लॉक का उपयोग करते हैं। आइए एक छोटे से उदाहरण पर विचार करें:
SET XACT_ABORT ON
IF object_id('tempdb..#t') IS NOT NULL
DROP TABLE #t
CREATE TABLE #t (i INT NOT NULL PRIMARY KEY)
BEGIN TRAN
INSERT INTO #t (i) VALUES (1)
INSERT INTO #t (i) VALUES (2)
INSERT INTO #t (i) VALUES (3)
INSERT INTO #t (i) VALUES (1) -- dup key error, XACT_ABORT kills the batch
INSERT INTO #t (i) VALUES (4)
COMMIT TRAN
SELECT * FROM #t
जब चौथा इंसर्ट एक त्रुटि का कारण बनता है, तो बैच समाप्त हो जाता है और लेनदेन वापस आ जाता है। अब तक कोई आश्चर्य नहीं।
आइए अब उस त्रुटि को TRY/CATCH ब्लॉक के साथ संभालने का प्रयास करें:
SET XACT_ABORT ON
IF object_id('tempdb..#t') IS NOT NULL
DROP TABLE #t
CREATE TABLE #t (i INT NOT NULL PRIMARY KEY)
BEGIN TRAN
INSERT INTO #t (i) VALUES (1)
INSERT INTO #t (i) VALUES (2)
BEGIN TRY
INSERT INTO #t (i) VALUES (3)
INSERT INTO #t (i) VALUES (1) -- dup key error
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE()
END CATCH
INSERT INTO #t (i) VALUES (4)
/* Error the Current Transaction cannot be committed and
cannot support operations that write to the log file. Roll back the transaction. */
COMMIT TRAN
SELECT * FROM #t
हमने डुप्लिकेट कुंजी त्रुटि पकड़ी, लेकिन अन्यथा, हम बेहतर नहीं हैं। हमारा बैच अभी भी समाप्त हो गया है, और हमारा लेनदेन अभी भी वापस आ गया है। कारण वास्तव में बहुत आसान है:
TRY/CATCH ब्लॉक लेन-देन को प्रभावित नहीं करते हैं।
XACT_ABORT ON होने के कारण, जिस क्षण डुप्लीकेट कुंजी त्रुटि होती है, लेन-देन बर्बाद हो जाता है। के लिए किया गया है। यह घातक रूप से घायल हो गया है। यह दिल के माध्यम से गोली मार दी गई है ... और त्रुटि को दोष देना है। TRY/CATCH SQL सर्वर देता है ... एक बुरा नाम। (क्षमा करें, विरोध नहीं कर सका)
दूसरे शब्दों में, यह कभी नहीं . होगा प्रतिबद्ध हैं और करेंगे हमेशा वापस लुढ़क जाना। एक TRY/CATCH ब्लॉक लाश को गिराने के लिए केवल इतना ही कर सकता है। हम XACT_STATE () . का उपयोग कर सकते हैं यह देखने के लिए कार्य करता है कि क्या हमारा लेनदेन प्रतिबद्ध है। यदि ऐसा नहीं है, तो लेनदेन को वापस लेने का एकमात्र विकल्प है।
SET XACT_ABORT ON -- Try with it OFF as well.
IF object_id('tempdb..#t') IS NOT NULL
DROP TABLE #t
CREATE TABLE #t (i INT NOT NULL PRIMARY KEY)
BEGIN TRAN
INSERT INTO #t (i) VALUES (1)
INSERT INTO #t (i) VALUES (2)
SAVE TRANSACTION Save1
BEGIN TRY
INSERT INTO #t (i) VALUES (3)
INSERT INTO #t (i) VALUES (1) -- dup key error
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE()
IF XACT_STATE() = -1 -- Transaction is doomed, Rollback everything.
ROLLBACK TRAN
IF XACT_STATE() = 1 --Transaction is commitable, we can rollback to a save point
ROLLBACK TRAN Save1
END CATCH
INSERT INTO #t (i) VALUES (4)
IF @@TRANCOUNT > 0
COMMIT TRAN
SELECT * FROM #t
ट्रिगर हमेशा लेन-देन के संदर्भ में निष्पादित होते हैं, इसलिए यदि आप उनके अंदर TRY/CATCH का उपयोग करने से बच सकते हैं, तो चीजें बहुत आसान होती हैं।
आपकी समस्या के समाधान के लिए, एक CLR Stored Proc डायनेमिक SQL को निष्पादित करने के लिए एक अलग कनेक्शन में SQL सर्वर से वापस कनेक्ट हो सकता है। आप एक नए लेन-देन में कोड को निष्पादित करने की क्षमता हासिल करते हैं और त्रुटि प्रबंधन तर्क को लिखना आसान है और C# में समझना आसान है।