सबसे पहले , आपको अपनी सभी प्रक्रियाओं में हमेशा उचित लेन-देन करना चाहिए, ताकि कोई फर्क नहीं पड़ता कि उन्हें ऐप कोड द्वारा बुलाया जाता है, किसी अन्य प्रक्रिया द्वारा, व्यक्तिगत रूप से एक ऐड-हॉक क्वेरी में, SQL एजेंट नौकरी या कुछ अन्य माध्यमों से। । लेकिन एकल डीएमएल स्टेटमेंट, या कोड जो कोई संशोधन नहीं करता है, को एक स्पष्ट लेनदेन की आवश्यकता नहीं है । इसलिए, मैं जो सिफारिश कर रहा हूं वह है:
- हमेशा TRY / CATCH संरचना है ताकि त्रुटियों को ठीक से बुदबुदाया जा सके
- वैकल्पिक रूप से नीचे दिए गए कोड में 3 ट्रांजेक्शन हैंडलिंग टुकड़े शामिल करें यदि आपके पास कई डीएमएल स्टेटमेंट हैं (चूंकि एक स्टेटमेंट अपने आप में एक लेनदेन है)। फिर भी, कुछ अतिरिक्त कोड जोड़ने के बाहर जहां इसकी विशेष आवश्यकता नहीं है, यदि कोई एक सुसंगत टेम्पलेट रखना पसंद करता है, तो यह 3 लेन-देन से संबंधित IF ब्लॉकों में रखने के लिए चोट नहीं पहुंचाता है। लेकिन उस मामले में मैं अभी भी सिलेक्ट-ओनली (यानी केवल पढ़ने के लिए) प्रोक्स के लिए 3 ट्रांजेक्शन से संबंधित आईएफ ब्लॉक नहीं रखने की सलाह दूंगा।
2 या अधिक डीएमएल स्टेटमेंट करते समय, आपको निम्नलिखित की तर्ज पर कुछ का उपयोग करने की आवश्यकता होती है (जो सिंगल डीएमएल ऑपरेशंस के लिए भी किया जा सकता है, यदि कोई सुसंगत होना पसंद करता है):
CREATE PROCEDURE [SchemaName].[ProcedureName]
(
@Param DataType
...
)
AS
SET NOCOUNT ON;
DECLARE @InNestedTransaction BIT;
BEGIN TRY
IF (@@TRANCOUNT = 0)
BEGIN
SET @InNestedTransaction = 0;
BEGIN TRAN; -- only start a transaction if not already in one
END;
ELSE
BEGIN
SET @InNestedTransaction = 1;
END;
-- { 2 or more DML statements (i.e. INSERT / UPDATE / DELETE) }
IF (@@TRANCOUNT > 0 AND @InNestedTransaction = 0)
BEGIN
COMMIT;
END;
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0 AND @InNestedTransaction = 0)
BEGIN
ROLLBACK;
END;
DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE(),
@ErrorState INT = ERROR_STATE(),
@ErrorSeverity INT = ERROR_SEVERITY();
-- optionally concatenate ERROR_NUMBER() and/or ERROR_LINE() into @ErrorMessage
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
RETURN;
END CATCH;
केवल 1 डीएमएल स्टेटमेंट या सिर्फ एक सेलेक्ट करते समय, आप बस निम्नलिखित के साथ दूर हो सकते हैं:
CREATE PROCEDURE [SchemaName].[ProcedureName]
(
@Param DataType
...
)
AS
SET NOCOUNT ON;
BEGIN TRY
-- { 0 or 1 DML statements (i.e. INSERT / UPDATE / DELETE) }
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE(),
@ErrorState INT = ERROR_STATE(),
@ErrorSeverity INT = ERROR_SEVERITY();
-- optionally concatenate ERROR_NUMBER() and/or ERROR_LINE() into @ErrorMessage
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
RETURN;
END CATCH;
दूसरा , आपको ऐप लेयर में लेन-देन तभी करना चाहिए जब आपको 1 से अधिक क्वेरी / संग्रहित प्रक्रिया निष्पादित करने की आवश्यकता हो और उन्हें सभी को एक परमाणु ऑपरेशन में समूहीकृत करना हो। एक ही करना एक SqlCommand.Execute___
कोशिश / पकड़ में होना चाहिए, लेकिन लेन-देन में नहीं।
लेकिन, क्या यह केवल एक कॉल करते समय ऐप लेयर में ट्रांजेक्शन करने में चोट करता है ? यदि इसके लिए MSDTC (Microsoft डिस्ट्रिब्यूटेड ट्रांजैक्शन कोऑर्डिनेटर) की आवश्यकता होती है, तो स्पष्ट रूप से आवश्यकता नहीं होने पर ऐप लेयर पर ऐसा करना सिस्टम पर थोड़ा भारी पड़ता है। व्यक्तिगत रूप से, मैं ऐप लेयर-आधारित लेन-देन से बचना पसंद करता हूं जब तक कि यह बिल्कुल आवश्यक नहीं है क्योंकि यह अनाथ लेनदेन की क्षमता में कटौती करता है (यदि प्रतिबद्ध या रोलबैक करने से पहले ऐप कोड के साथ कुछ गलत हुआ)। मैंने यह भी पाया है कि यह कभी-कभी डिबगिंग को कुछ स्थितियों को थोड़ा और कठिन बना देता है। लेकिन उस से किया जा रहा ने कहा, मैं कुछ भी नहीं दिख रहा है तकनीकी रूप से गलत भी जब एक ही बनाने एप्लिकेशन परत पर लेन-देन से निपटने procकहते हैं; फिर, एक एकल डीएमएल स्टेटमेंट का अपना लेनदेन है और इसे किसी भी स्तर पर किसी भी स्पष्ट लेनदेन से निपटने की आवश्यकता नहीं है ।