سؤال

أنا أعمل على مشروع Nhibernate ولدي سؤال بخصوص تحديث الكيانات العابرة.

في الأساس سير العمل كما يلي:

  1. إنشاء DTO (إسقاط) وإرسال السلك إلى العميل. هذا له مجموعة فرعية صغيرة من الخصائص من الكيان.
  2. العميل يرسل DTO المتغير
  3. قم بتخطيط خصائص DTO مرة أخرى إلى الصناديق المناسبة بحيث يمكن إنشاء عبارة تحديث وتنفيذها بواسطة NH.
  4. حفظ الكيان

النقطة 4 هي المكان الذي أمتلك فيه القضية. حاليًا يمكنني تحقيق هذا التحديث باستخدام طريقة Session.merge () ، ومع ذلك يجب أولاً تحميل الكيان من DB (لا تفترض رقم 2LC) قبل التحديث. لذلك ، يتم إطلاق بيان محدد وتحديث.

ما أود القيام به هو إنشاء مثيل عابر للكيان ، قم بتخطيط القيم الجديدة من DTO ، ثم قم بإنشاء عبارة SQL باستخدام الخصائص التي قمت بتغييرها فقط. يجب أن يكون الاختيار الإضافي غير ضروري لأن لدي بالفعل معرف الكيان والقيم المطلوبة للفقرة المحددة. هل هذا ممكن في NH؟

باستخدام Session.update () حاليًا ، سيتم تضمين جميع الخصائص في بيان التحديث ويتم إثارة استثناء بسبب الخصائص غير المخصصة التي ليست جزءًا من DTO.

في الأساس ، أحتاج إلى طريقة لتحديد خصائص الكيان القذرة ، لذا يتم تضمينها فقط في التحديث.

== تحرير ==

علي سبيل المثال...

public class Person
{
    public virtual int PersonId { get; set; }
    public virtual string Firstname { get; set; }   
    public virtual string Nickname { get; set; }    
    public virtual string Surname { get; set; } 
    public virtual DateTime BirthDate { get; set; }     
}

وحالة الاختبار.

// Create the transient entity
Person p = new Person()
p.id = 1;

using (ISession session = factory.OpenSession())
{
    session.Update(p);

    // Update the entity – now attached to session    
    p.Firstname = “Bob”;

    session.Flush();
}

كنت آمل في إنشاء بيان SQL مماثل لـ "تحديث الأشخاص الذين تم تعيينهم firstName = 'bob' حيث الشخص = 1 '. بدلاً من ذلك ، أحصل على وقت خارج نطاق الاستثناء بسبب عدم تهيئة تاريخ الميلاد. لا ينبغي أن تحتاج إلى عملية ميلاد لأنه غير مطلوب لبيان SQL. ربما هذا غير ممكن؟

== /edit ==

شكرا مقدما ، جون

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

المحلول

التحديث الديناميكي هو ما تبحث عنه. في ملف التعيين الخاص بك (hbm.xml):

<class name="Foo" dynamic-update="true">
   <!-- remainder of your class map -->

كن على دراية بالمشاكل المحتملة التي قد يسببها هذا. دعنا نقول أن لديك بعض منطق المجال الذي يقول إما الاسم الأول أو الاسم المستعار يجب ألا يكون فارغًا. (صنع هذا تمامًا.) يقوم شخصان بتحديث جون "جونوي" جونسون في نفس الوقت. واحد يزيل اسمه الأول. نظرًا لأن التحديث الديناميكي صحيح ، فإن عبارة التحديث لاغية إلى جون والسجل الآن "Jonboy" Jonson. التحديث الآخر المتزامن يزيل لقبه. القصد هو جون جونوي. ولكن يتم إرسال فقط خالية من اللقب إلى قاعدة البيانات. لديك الآن سجل بدون اسم أو لقب. إذا كان التحديث الديناميكي كاذبًا ، فسيقوم التحديث الثاني بتعيينه على جون جونوي. ربما هذه ليست مشكلة في موقفك ، ولكن وضع التحديث الديناميكي = "صحيح" له عواقب ويجب أن تفكر من خلال الآثار المترتبة.

تحديث: شكرا على الرمز. ساعد ذلك. المشكلة الأساسية هي عدم وجود معلومات كافية. عندما تقول Session.update (P) ، يتعين على Nhibernate ربط كيان منفصل بالجلسة الحالية. لديها PK غير Default. لذلك يعرف nhibernate أنه تحديث وليس ملحق. عندما تقول Session.update (P) ، يرى Nhibernate أن الكيان بأكمله متسخ ويرسله إلى قاعدة البيانات. (إذا كنت تستخدم Session.merge (OBJ) ، فإن Nhibernate يختار الكيان من قاعدة البيانات ودمج OBJ معه.) هذا ليس ما تعنيه حقًا. تريد ربط كائنك بالجلسة الحالية ، ولكن ضع علامة عليه على أنه نظيف. واجهة برمجة التطبيقات غير بديهية إلى حد ما. يمكنك استخدام Session.lock (OBJ ، lockmode.none) على النحو التالي.

using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction()) {
    var p = new Person {PersonId = 1};
    session.Lock(p, LockMode.None); // <-- This is the secret sauce!
    p.Firstname = "Bob";
    // No need to call session.Update(p) since p is already associated with the session.
    tx.Commit();
}

(تم تحديد NB Dynamic-update = "true" في التعيين الخاص بي.)

ينتج عن هذا SQL التالي:

UPDATE Person
SET    Firstname = 'Bob' /* @p0_0 */
WHERE  PersonId = 1 /* @p1_0 */
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top