كيفية إضافة كائن جديد إلى Ilist المعين كواحد إلى كثير مع أحمق؟

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

سؤال

نموذجي يحتوي على فئة Section التي لديها قائمة أمر بها Statics التي هي جزء من هذا القسم. ترك جميع الخصائص الأخرى خارج، يبدو تنفيذ النموذج مثل هذا:

public class Section
{
    public virtual int Id { get; private set; }
    public virtual IList<Static> Statics { get; private set; }
}

public class Static
{
    public virtual int Id { get; private set; }
}

في قاعدة البيانات، يتم تطبيق العلاقة كواحد إلى كثير، حيث الجدول Static لديه مفتاح أجنبي يشير إلى Section وعمدة عدد صحيح Position لتخزين موضع الفهرس في القائمة هو جزء منه.

يتم التعيين في أحمق بطلاقة مثل هذا:

public SectionMap()
{
    Id(x => x.Id);
    HasMany(x => x.Statics).Cascade.All().LazyLoad()
            .AsList(x => x.WithColumn("Position"));
}

public StaticMap()
{
    Id(x => x.Id);
    References(x => x.Section);
}

الآن أنا قادر على تحميل القائمة StaticS، وأنا أيضا قادر على تحديث تفاصيل تلك. ومع ذلك، لا أستطيع أن أجد طريقة لإضافة جديدة StaticS إلى Section, ، ولدي هذا التغيير استمر في قاعدة البيانات. لقد جربت العديد من مجموعات من:

  • mySection.Statics.Add(myStatic)
  • session.Update(mySection)
  • session.Save(myStatic)

ولكن الأقرب الذي حصلت عليه (باستخدام أول بيانين)، هو قراءة استثناء SQL: "لا يمكن إدراج القيمة NULL في وضع العمود" ". من الواضح أن INSERT تتم محاولة هنا، ولكن لا يبدو أن Lihibernate لاحقا موضع الفهرس تلقائيا ببيان SQL.

ما الخطأ الذي افعله؟ هل أفتقد شيئا في تعييناتي؟ هل أحتاج إلى فضح Position عمود كخاصية وتعيين قيمة لذلك بنفسي؟

تعديل: يبدو أن كل شيء يعمل كما هو متوقع، إذا قمت بإزالة NOT NULL القيد على Static.Position عمود في قاعدة البيانات. أعتقد أن Lhibernate يجعل الإدراج وفورا بعد تحديث الصف مع Position القيمة.

في حين أن هذا هو مغذور على السؤال، لست متأكدا مما إذا كان الأفضل. كنت أفضل Position العمود ليتم عدم ظهور العمود، لذلك ما زلت آمل أن يكون هناك طريقة لجعل أحمق توفير قيمة لهذا العمود مباشرة في INSERT بيان.

وبالتالي، فإن السؤال لا يزال مفتوحا. أي حلول أخرى؟

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

المحلول

عند استخدام علاقة ثنائية الاتجاهية، يجب أن تكون إحدى النهايات "معكوس". أفضل الممارسات هي ضبط النهاية مع المجموعة على أنها معكوس، لأن ذلك يتجنب عبارات SQL غير الضرورية ويسمح لعمود الهوية بأنك "لا لاغية".

في القسم 6.4. من الوثائق التي يمكنك العثور عليها ملاحظة التالية:

ملاحظة مهمة للغاية: إذا تم الإعلان عن عمود الجمعية غير فارغ، فقد يتسبب nhibernate في انتهاكات القيود عند إنشاء أو تحديث الجمعية. لمنع هذه المشكلة، يجب عليك استخدام ارتباط ثنائي الاتجاه مع العديد من الطرفين القيمة (المجموعة أو الحقيبة) التي تحمل علامة كوسفية = "True". انظر مناقشة الجمعيات ثنائية الاتجاه في وقت لاحق من هذا الفصل.

لذلك، تحتاج إلى إضافة .inverse () لرسم خرائط الخاص بك في SectionMap.

public SectionMap()
{
    Id(x => x.Id);
    HasMany(x => x.Statics)
        .Cascade.All()
        .LazyLoad()
        .Inverse()
        .AsList(x => x.WithColumn("Position"));
}

ربما تريد أيضا طريقة إضافة وإزالة طريقة في القسم، والتي تقوم بتعيين / إعادة تعيين مرجع ثابت بالإضافة إلى إضافة / إزالة الثابت إلى / من مجموعتها الخاصة:

public virtual void AddStatic(Static static)
{
    Statics.Add(static);
    static.Section = this;
}


public virtual void RemoveStatic(Static static)
{
    Statics.Remove(static);
    static.Section = null;
}

تتأكد هذه الطرق من الاحتفاظ بالمراجع دقيقة على جانبي العلاقة.

وفق القسم 6.8. لا يدعم المستندات Nibernate علاقات ثنائية الاتجاه عند استخدام المجموعات المفهرسة:

يرجى ملاحظة أن Lhibernate لا يدعم جمعيات ثنائية الاتجاهية من غرفة واحدة مع مجموعة مفهرسة (قائمة أو خريطة أو صفيف) ك "العديد" الطرف "، عليك استخدام تعيين مجموعة أو حقيبة.

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

نصائح أخرى

في جدول ثابت، يكون لديك حقل يسمى "SectionID" أو شيء مشابه. اسمحوا أن يكون هذا الحقل نلاوة: يضيف Nibernate أولا السجل الجديد، ثم يقوم بتحديث الهوية المرجعية.

لقد وجدت أنه في DB الخاص بي وأنا فوجئت أيضا: لماذا لا يحب NH المراجع المناسبة على مستوى قاعدة البيانات؟

اعتقدت أنني سأرمي في 0.02 دولار، فقط لأنني جئت إلى هنا أتطلع إلى حل مشكلتك، ويبدو أن أيا من الإجابات تعمل بالفعل.

أنت تقريبا هناك في الحل الخاص بك. رسم الخرائط الخاصة بك للحصول على hasmany هو الصحيح. المشكلة هي، كما قلت، لا يتم تحديث الموقف في قاعدة البيانات (FWIW عند تعيينه إلى NULL، أنه "يعمل فقط" لأنه يتم إدراج NULL في DB؛ بالنسبة لي هذا ليس يعمل حقا؛) ).

أجد أنه غريب بعض الشيء، فأنت بحاجة إلى تعيين الموضع على فئة ثابتة لديك أيضا، ومن الواضح أن تشمل خاصية موضعية على ثابت. لا تريد أن تكون خاصية الموضع مثبتة، لأنه يتم تحديد القيمة من خلال حيث يوجد ثابت في القائمة.

أضف ما يلي ثابت

public virtual int Position 
{
    get 
    {
        // Will throw exception if Section is null
        // or Section.Statics is null...
        return Section.Statics.IndexOf(this);
    }
    protected set 
    {
    }
}

مع وجود ذلك في عمود الموضع في DB سيتم تحديث (تذكر تعيين موقعك في Staticmap الخاص بك).

أنا أظن أن وكيل Nib Static يمكن تحديث حقل الموضع اعتمادا على موقعه في القائمة (من قبل سحر أكبر مما أملك) وهذا يتم حفظه بعد ذلك على DB.

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