NHibernate Session.Flush() إرسال استعلامات التحديث عند عدم حدوث أي تحديث

StackOverflow https://stackoverflow.com/questions/34852

  •  09-06-2019
  •  | 
  •  

سؤال

لدي جلسة NHibernate.في هذه الجلسة، أقوم بإجراء عملية واحدة بالضبط، وهي تشغيل هذا الرمز للحصول على قائمة:

public IList<Customer> GetCustomerByFirstName(string customerFirstName)
{
return _session.CreateCriteria(typeof(Customer))
    .Add(new NHibernate.Expression.EqExpression("FirstName", customerFirstName))
    .List<Customer>();
}

أنا أتصل Session.Flush() عند نهاية ال HttpRequest, ، وأحصل على HibernateAdoException.يقوم NHibernate بتمرير بيان تحديث إلى قاعدة البيانات، ويتسبب في انتهاك المفتاح الخارجي.إذا لم أقم بتشغيل flush, ، يكتمل الطلب دون أي مشكلة.المشكلة هنا هي أنني أحتاج إلى تنفيذ التدفق في حالة حدوث تغيير خلال جلسات أخرى، حيث يتم إعادة استخدام هذا الرمز في مناطق أخرى.هل هناك إعداد تكوين آخر قد أفتقده؟


إليك الكود من الاستثناء:

[SQL: UPDATE CUSTOMER SET first_name = ?, last_name = ?, strategy_code_1 = ?, strategy_code_2 = ?, strategy_code_3 = ?, dts_import = ?, account_cycle_code = ?, bucket = ?, collector_code = ?, days_delinquent_count = ?, external_status_code = ?, principal_balance_amount = ?, total_min_pay_due = ?, current_balance = ?, amount_delinquent = ?, current_min_pay_due = ?, bucket_1 = ?, bucket_2 = ?, bucket_3 = ?, bucket_4 = ?, bucket_5 = ?, bucket_6 = ?, bucket_7 = ? WHERE customer_account_id = ?]

لا تظهر أية معلمات على أنها تم تمريرها.

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

المحلول

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

نصائح أخرى

كن حذرًا دائمًا مع الحقول NULLable عندما تتعامل مع NHibernate.إذا كان الحقل الخاص بك NULLable في قاعدة البيانات، فتأكد من أن فئة .NET المقابلة تستخدم النوع Nullable أيضًا.وإلا فإن كل أنواع الأشياء الغريبة ستحدث.عادةً ما يكون العَرض هو أن NHibernate سيحاول تحديث السجل في قاعدة البيانات، على الرغم من أنك لم تقم بتغيير أي حقول منذ أن قرأت الكيان من قاعدة البيانات.

يوضح التسلسل التالي سبب حدوث ذلك:

  1. يقوم NHibernate باسترداد بيانات الكيان الأولية من قاعدة البيانات باستخدام ADO.NET
  2. يقوم NHibernate ببناء الكيان وتعيين خصائصه
  3. إذا كان حقل قاعدة البيانات يحتوي على NULL، فسيتم تعيين الخاصية على القيمة الافتراضية لنوعها:
    • سيتم تعيين خصائص الأنواع المرجعية على قيمة خالية
    • سيتم تعيين خصائص أنواع الأعداد الصحيحة والفاصلة العائمة على 0
    • سيتم تعيين خصائص النوع المنطقي على خطأ
    • سيتم تعيين خصائص نوع DateTime على DateTime.MinValue
    • إلخ.
  4. الآن، عند تنفيذ المعاملة، يقوم NHibernate بمقارنة قيمة الخاصية بقيمة الحقل الأصلي الذي يقرأه من نموذج قاعدة البيانات، وبما أن الحقل يحتوي على NULL ولكن الخاصية تحتوي على قيمة غير فارغة، تعتبر NHibernate الخاصية قذرة، وتفرض تحديثًا للكيان.

لا يضر هذا بالأداء فقط (تحصل على رحلة إضافية ذهابًا وإيابًا إلى قاعدة البيانات وتحديث إضافي في كل مرة تقوم فيها باسترداد الكيان) ولكنه قد يتسبب أيضًا في صعوبة استكشاف أخطاء أعمدة DateTime وإصلاحها.في الواقع، عند تهيئة خاصية DateTime إلى قيمتها الافتراضية، يتم تعيينها على 1/1/0001.عندما يتم حفظ هذه القيمة في قاعدة البيانات، لا يستطيع SqlClient الخاص بـ ADO.NET تحويلها إلى قيمة SqlDateTime صالحة نظرًا لأن أصغر SqlDateTime ممكن هو 1/1/1753!!!

الحل الأسهل هو جعل خاصية الفئة تستخدم النوع Nullable، في هذه الحالة "DateTime؟".وبدلاً من ذلك، يمكنك تنفيذ مخطط نوع مخصص من خلال تطبيق IUserType باستخدام أسلوب Equals الخاص به بشكل صحيح مقارنة DbNull.Value بأي قيمة افتراضية لنوع القيمة الخاص بك.في حالتنا، ستحتاج المساواة إلى إرجاع صحيح عند مقارنة 1/1/0001 مع DbNull.Value.إن تنفيذ IUserType كامل الوظائف ليس بالأمر الصعب حقًا ولكنه يتطلب معرفة معلومات NHibernate التافهة، لذا استعد للقيام ببعض عمليات البحث الكبيرة على Google إذا اخترت السير بهذه الطريقة.

لقد واجهت هذه المشكلة أيضًا في NH 2.0.1 عند محاولة إخفاء الأطراف العكسية لأكياس متعدد إلى متعدد باستخدام Access = "noop" (تلميح:هذا لا يعمل).

أدى تحويلها إلى Access = "field" + إضافة حقل في الفصل إلى حل المشكلة.من الصعب جدًا تعقبهم بالرغم من ذلك.

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