سؤال

ما هي أفضل الممارسات لإجراء المعاملات في C# .Net 2.0.ما هي الفئات التي ينبغي استخدامها؟ما هي المزالق التي يجب البحث عنها وما إلى ذلك.كل تلك الأشياء المتعلقة بالالتزام والتراجع.لقد بدأت للتو مشروعًا قد أحتاج فيه إلى إجراء بعض المعاملات أثناء إدخال البيانات في قاعدة البيانات.نرحب بأي ردود أو روابط حتى للأشياء الأساسية المتعلقة بالمعاملات.

هل كانت مفيدة؟

المحلول

هناك نوعان رئيسيان من المعاملات؛معاملات الاتصال والمعاملات المحيطة.ترتبط معاملة الاتصال (مثل SqlTransaction) مباشرة باتصال قاعدة البيانات (مثل SqlConnection)، مما يعني أنه يتعين عليك الاستمرار في تمرير الاتصال - حسنًا في بعض الحالات، ولكن لا يسمح بـ "إنشاء/استخدام/تحرير" الاستخدام، ولا يسمح بالعمل عبر قاعدة البيانات.مثال (منسق للمساحة):

using (IDbTransaction tran = conn.BeginTransaction()) {
    try {
        // your code
        tran.Commit();
    }  catch {
        tran.Rollback();
        throw;
    }
}

ليس فوضويًا جدًا، ولكنه يقتصر على اتصالنا "conn".إذا أردنا استدعاء أساليب مختلفة، فنحن بحاجة الآن إلى تمرير "conn".

البديل هو معاملة محيطة؛الجديد في .NET 2.0، نطاق المعاملة يسمح الكائن (System.Transactions.dll) بالاستخدام عبر نطاق من العمليات (سيتم إدراج الموفرين المناسبين تلقائيًا في المعاملة المحيطة).وهذا يجعل من السهل التكيف مع التعليمات البرمجية الموجودة (غير المتعلقة بالمعاملات)، والتحدث مع العديد من مقدمي الخدمة (على الرغم من أن DTC سوف تتدخل إذا تحدثت إلى أكثر من مقدم واحد).

على سبيل المثال:

using(TransactionScope tran = new TransactionScope()) {
    CallAMethodThatDoesSomeWork();
    CallAMethodThatDoesSomeMoreWork();
    tran.Complete();
}

لاحظ هنا أن الطريقتين يمكنهما التعامل مع اتصالاتهما الخاصة (فتح/استخدام/إغلاق/تخلص)، إلا أنهما ستصبحان بصمت جزءًا من المعاملة المحيطة دون الحاجة إلى تمرير أي شيء.

إذا كانت هناك أخطاء في التعليمات البرمجية، فسيتم استدعاء Dispose() بدون Complete()، لذلك سيتم التراجع عنها.يتم دعم التداخل المتوقع وما إلى ذلك، على الرغم من أنه لا يمكنك التراجع عن معاملة داخلية بعد إكمال المعاملة الخارجية:إذا كان أي شخص غير سعيد، يتم إحباط الصفقة.

الميزة الأخرى لـ TransactionScope هي أنها ليست مرتبطة بقواعد البيانات فقط؛يمكن لأي مزود علم بالمعاملات استخدامه.صندوق رأس المال العامل، على سبيل المثال.أو حتى أن هناك بعض نماذج الكائنات المتوافقة مع TransactionScope (على سبيل المثال.فئات .NET مع إمكانية التراجع - ربما أسهل من التذكار، على الرغم من أنني لم أستخدم هذا الأسلوب بنفسي مطلقًا).

على العموم موضوع مفيد جدا جدا

بعض التحذيرات:

  • في SQL Server 2000، سينتقل TransactionScope إلى DTC على الفور؛تم إصلاح هذا في SQL Server 2005 والإصدارات الأحدث، ويمكنه استخدام LTM (أقل بكثير من الحمل) حتى تتحدث إلى مصدرين وما إلى ذلك، عندما يتم ترقيته إلى DTC.
  • هناك خلل هذا يعني أنك قد تحتاج إلى تعديل سلسلة الاتصال الخاصة بك

نصائح أخرى

protected void Button1_Click(object sender, EventArgs e)
   {


       using (SqlConnection connection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database.mdf;Integrated Security=True;User Instance=True"))
       {
           connection1.Open();

           // Start a local transaction.
           SqlTransaction sqlTran = connection1.BeginTransaction();

           // Enlist a command in the current transaction.
           SqlCommand command = connection1.CreateCommand();
           command.Transaction = sqlTran;

           try
           {
               // Execute two separate commands.
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('a','b','c')";
               command.ExecuteNonQuery();
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('x','y','z')";
               command.ExecuteNonQuery();

               // Commit the transaction.
               sqlTran.Commit();
               Label3.Text = "Both records were written to database.";
           }
           catch (Exception ex)
           {
               // Handle the exception if the transaction fails to commit.
               Label4.Text = ex.Message;


               try
               {
                   // Attempt to roll back the transaction.
                   sqlTran.Rollback();
               }
               catch (Exception exRollback)
               {
                   // Throws an InvalidOperationException if the connection 
                   // is closed or the transaction has already been rolled 
                   // back on the server.
                   Label5.Text = exRollback.Message;

               }
           }
       }


   }

ويمكنك أيضا لف الصفقة تصل الى انها الإجراء المخزن الخاص والتعامل معها بهذه الطريقة بدلا من القيام بالمعاملات في C # نفسها.

وإذا كنت بحاجة فقط لأنها الاشياء المتعلقة ديسيبل، بعض OR المخططون (مثل NHibernate) transactinos الدعم من خارج منطقة الجزاء في الافتراضية.

يعتمد ذلك أيضًا على ما تحتاجه.بالنسبة لمعاملات SQL الأساسية، يمكنك محاولة إجراء معاملات TSQL باستخدام BEGIN TRANS وCOMMIT TRANS في التعليمات البرمجية الخاصة بك.هذه هي الطريقة الأسهل ولكنها معقدة وعليك أن تكون حريصًا على الالتزام بشكل صحيح (والتراجع).

سأستخدم شيئًا مثل

SQLTransaction trans = null;
using(trans = new SqlTransaction)
{
    ...
    Do SQL stuff here passing my trans into my various SQL executers
    ...
    trans.Commit  // May not be quite right
}

أي فشل سوف يخرجك مباشرة من using وسيتم دائمًا الالتزام بالمعاملة أو التراجع عنها (اعتمادًا على ما تطلب منها القيام به).أكبر مشكلة واجهناها هي التأكد من التزامها دائمًا.يضمن الاستخدام أن نطاق المعاملة محدود.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top