سؤال

أحد الأشياء التي تجعلني في حيرة من أمري هو استخدام session.Flush،بالتزامن مع session.Commit, ، و session.Close.

أحيانا session.Close يعمل، على سبيل المثال، ينفذ جميع التغييرات التي أحتاجها.أعلم أنني بحاجة إلى استخدام الالتزام عندما يكون لدي معاملة، أو وحدة عمل بها عدة عمليات إنشاء/تحديث/حذف، حتى أتمكن من اختيار التراجع في حالة حدوث خطأ.

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

هل لدى أي شخص إرشادات جيدة حول مكان أو متى يتم استخدام Flush؟لقد قمت بمراجعة وثائق NHibernate لهذا الغرض، ولكن ما زلت لا أستطيع العثور على إجابة واضحة.

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

المحلول

باختصار:

  1. استخدم المعاملات دائمًا
  2. لا تستخدم Close(), ، بدلاً من ذلك قم بلف مكالماتك على ISession داخل using بيان أو إدارة دورة حياة ISession الخاصة بك في مكان آخر.

من وثائق:

من وقت لآخر ISession سيتم تنفيذ عبارات SQL اللازمة لمزامنة حالة اتصال ADO.NET مع حالة الكائنات الموجودة في الذاكرة.تحدث هذه العملية، التدفق، بشكل افتراضي في النقاط التالية

  • من بعض الدعوات Find() أو Enumerable()
  • من NHibernate.ITransaction.Commit()
  • من ISession.Flush()

يتم إصدار عبارات SQL بالترتيب التالي

  1. جميع عمليات إدخال الكيانات، بنفس الترتيب الذي تم به حفظ الكائنات المقابلة ISession.Save()
  2. جميع تحديثات الكيان
  3. جميع عمليات حذف المجموعة
  4. جميع عمليات حذف عناصر المجموعة والتحديثات والإدراجات
  5. جميع إدراجات المجموعة
  6. جميع عمليات حذف الكيانات، بنفس الترتيب الذي تم به حذف الكائنات المقابلة ISession.Delete()

(الاستثناء هو أن الكائنات التي تستخدم إنشاء المعرف الأصلي يتم إدراجها عند حفظها.)

إلا عندما صريحة Flush(), ، لا توجد أي ضمانات على الإطلاق بشأن وقت تنفيذ الجلسة لاستدعاءات ADO.NET، فقط ترتيب تنفيذها.ومع ذلك، فإن NHibernate يضمن أن ISession.Find(..) لن تقوم الأساليب أبدًا بإرجاع البيانات القديمة؛ولن يعيدوا البيانات الخاطئة.

من الممكن تغيير السلوك الافتراضي بحيث يحدث التدفق بشكل أقل تكرارًا.ال FlushMode يحدد الفصل ثلاثة أوضاع مختلفة:يتم التدفق فقط في وقت الالتزام (وفقط عندما يتم تشغيل NHibernate ITransaction يتم استخدام واجهة برمجة التطبيقات)، أو يتم التدفق تلقائيًا باستخدام الروتين الموضح، أو لا يتم التدفق أبدًا إلا إذا Flush() يسمى صراحة.الوضع الأخير مفيد لوحدات العمل طويلة الأمد، حيث ISession يتم الاحتفاظ بها مفتوحة ومنفصلة لفترة طويلة.

...

راجع أيضا هذا القسم:

يتضمن إنهاء الجلسة أربع مراحل متميزة:

  • مسح الجلسة
  • ارتكاب الصفقة
  • إغلاق الجلسة
  • التعامل مع الاستثناءات

شطف الجلسة

إذا كنت تستخدم ITransaction API، لا داعي للقلق بشأن هذه الخطوة.سيتم تنفيذه ضمنيًا عند تنفيذ المعاملة.وإلا يجب عليك الاتصال ISession.Flush() للتأكد من أن كافة التغييرات متزامنة مع قاعدة البيانات.

تنفيذ معاملة قاعدة البيانات

إذا كنت تستخدم NHibernate ITransaction API، فسيبدو هذا كما يلي:

tx.Commit(); // flush the session and commit the transaction

إذا كنت تدير معاملات ADO.NET بنفسك، فيجب عليك ذلك يدويًا Commit() معاملة ADO.NET.

sess.Flush();
currentTransaction.Commit();

إذا قررت عدم الالتزام بالتغييرات:

tx.Rollback();  // rollback the transaction

أو:

currentTransaction.Rollback();

إذا قمت بالتراجع عن المعاملة، فيجب عليك إغلاق الجلسة الحالية وتجاهلها على الفور للتأكد من اتساق الحالة الداخلية لـ NHibernate.

إغلاق الجلسة

دعوة ل ISession.Close() يمثل نهاية الجلسة.التأثير الرئيسي لـ Close() هو أنه سيتم التخلي عن اتصال ADO.NET خلال الجلسة.

tx.Commit();
sess.Close();

sess.Flush();
currentTransaction.Commit();
sess.Close();

إذا قمت بتوفير الاتصال الخاص بك، Close() تقوم بإرجاع مرجع إليه، بحيث يمكنك إغلاقه يدويًا أو إعادته إلى التجمع.خلاف ذلك Close() إعادته إلى حوض السباحة.

نصائح أخرى

بدءًا من NHibernate 2.0، تكون المعاملات مطلوبة لعمليات قاعدة البيانات.لذلك، ITransaction.Commit() سوف تتعامل المكالمة مع أي تنظيف ضروري.إذا كنت لا تستخدم معاملات NHibernate لسبب ما، فلن يكون هناك مسح تلقائي للجلسة.

من وقت لآخر، ستقوم ISession بتنفيذ عبارات SQL اللازمة لمزامنة حالة اتصال ADO.NET مع حالة الكائنات الموجودة في الذاكرة.

واستخدم دائمًا

 using (var transaction = session.BeginTransaction())
 {
     transaction.Commit();
 }

بعد تنفيذ التغييرات ثم حفظها في قاعدة البيانات نستخدم المعاملة.Commit();

فيما يلي مثالان على الكود الخاص بي حيث قد يفشل بدون session.Flush():

http://www.lucidcoding.blogspot.co.uk/2012/05/change-type-of-entity-persistence.html

في نهاية هذا، يمكنك رؤية قسم من التعليمات البرمجية حيث قمت بتعيين إدراج الهوية، وحفظ الكيان ثم مسحه، ثم إيقاف إدراج الهوية.بدون هذا التدفق، يبدو أنه يتم تشغيل إدراج الهوية وإيقاف تشغيلها ثم حفظ الكيان.

لقد منحني استخدام Flush() مزيدًا من التحكم في ما يحدث.

هنا مثال آخر:

إرسال رسالة NServiceBus داخل TransactionScope

لا أفهم تمامًا سبب هذا الأمر، لكن Flush() منعت حدوث الخطأ.

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