لن يتم حفظ الكيان الفرعي الجديد عند حفظ الكيان الأصلي

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

سؤال

لدي كيان الوالدين

foo الموجود في قاعدة البيانات، لدي خاصية bar على هذا الكيان (علاقة واحد إلى متعدد).

Foo تم فصله لأنه تم إلغاء تسلسله باستخدام WebApi، لذلك أفعل ذلك foo

context.Foos.AddOrUpdate(foo);

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

إذا فعلت context.Bars.AddOrUpdate(foo.Bar); قبل الاتصال context.Foos.AddOrUpdate(foo); سيحفظ الشريط الجديد بشكل صحيح في جدول الشريط، لكنه لن يضيف معرف الشريط الصحيح إلى جدول foo

@ يوليام شاندرا

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

var foo = new Foo();
foo.FooId = 524 //Existing foo;

foo.Bar = new Bar(); //Completely new bar    
db.Foos.AddOrUpdate(foo);
db.SaveChanges();

ولكن لا

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

المحلول

يحتاج العمل مع الكائنات المنفصلة إلى تعليمات برمجية إضافية.

إذا كنت تعمل مع الكائنات غير المتصل ، فيجب عليك إدارة التزامن يدويًا.

مصدر

لو Bar هو كيان موجود تحتاج إلى إرفاقه أولاً، لذلك Foo سيتم إضافتها كما Bar's أطفال.

if (foo.Bar.Id != 0)
{
    context.Bars.Attach(foo.Bar);
    context.Foos.AddOrUpdate(foo);
}

مثال الكود أعلاه مشابه لـ Course (Foo) و Department (Bar) مثال في هذا المقال.

لكن اذا Bar هو كيان جديد تحتاج فقط إلى إضافته Foo, ، ثم Bar سيتم إضافتها أيضًا.

else
{
    context.Foos.Add(foo);
}

يمكن التحقق من بعض الأنواع الأخرى إجابتي.

تحديث

قبل أن أشرح أكثر، أود أن أعرض رمزًا متطابقًا.

  • db.Set<T>().Add(instance) يساوي db.Entry(instance).State = EntityState.Added;
  • db.Set<T>().Attach(instance) يساوي db.Entry(instance).State = EntityState.Unchanged;

الجواب السابق أوضح شرطين.

  • New Foo والشريط الحالي

    context.Bars.Attach(foo.Bar);

    context.Foos.AddOrUpdate(foo);

  • نيو فو وبار جديد

    context.Foos.Add(foo);

تمت الإضافة الخاصة

Added له حالة خاصة، بمجرد وضع علامة على الكيان Added.سيتم وضع علامة على جميع الكيانات في الرسم البياني على أنها Added أيضًا، حتى لو كان أي كيان مرجعي عبارة عن كائن موجود في قاعدة البيانات.إذا كان لدينا هذا الرمز، ستتم إضافة Foo وBar.

var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Foo>().Add(foo);
db.SaveChanges();

لمنع حدوث ذلك، يجب إرفاق الشريط أولاً.

var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Bar>().Attach(bar);
db.Set<Foo>().Add(foo);
db.SaveChanges();

يفحص مقالة جولي ليرمان للحصول على شرح أكثر اكتمالا.

والسبب في حدوث ذلك هو أنه عند استخدام طريقة dbset.add (أي ، screencasts.add) ، ليس فقط حالة الكيان الجذري الذي تم وضع علامة عليه "إضافة" ، ولكن كل شيء في الرسم البياني لم يكن السياق على دراية به من قبل تمت إضافة علامة كذلك.على الرغم من أن المطور قد يدرك أن الموضوع له قيمة معرف موجودة ، فإن إطار عمل الكيان يكرم EntityState (إضافة) ويقوم بإنشاء أمر قاعدة بيانات إدراج للموضوع ، بغض النظر عن المعرف الحالي.

اضبط الشرح بناءً على التحديث الخاص بك

وسؤالك المحدث يتعلق بـ Foo الحالي والشريط الجديد.باستخدام الكود الخاص بك، لن تضيف النتيجة شريطًا جديدًا ولن يقوم Foo الحالي بإنشاء علاقة مع Bar الجديد.

var foo = new Foo();
foo.FooId = 524 //Existing foo;

foo.Bar = new Bar(); //Completely new bar    
db.Foos.AddOrUpdate(foo);
db.SaveChanges();

إذا أضفنا الشريط يدويًا مع AddOrUpdate(foo), ، والنتيجة لا تزال ليست كما هو متوقع.ستتم إضافة الشريط الجديد، لكن لن يكون لـ Foo علاقة بالشريط الجديد.

db.Bars.Add(foo.Bar);
db.Foos.AddOrUpdate(foo);

سلوك AddOrUpdate غير متناسق.

حل

إذا كنت تعمل مع الكائنات غير المتصل ، فيجب عليك إدارة التزامن يدويًا.

يجب أن يعمل هذا الرمز في جميع الظروف.

  • نيو فو و نيو بار
  • Foo الجديد والشريط الموجود
  • Foo الحالي والشريط الجديد
  • Foo الموجود والشريط الموجود

يعتمد هذا الرمز على المعرف (المعرف = 0 كيان جديد).

db.Entry(foo).State = 
       foo.FooId == 0 ? EntityState.Added : EntityState.Modified;
if (foo.Bar != null)
{
    db.Entry(foo.Bar).State = 
       foo.Bar.BarId == 0 ? EntityState.Added : EntityState.Modified;
                                                             ^^^
    // If you don't want to change the Bar while creating a relationship between
    // Foo and with existing Bar, you can change 
    // `EntityState.Modified` with `EntityState.Unchanged`
}
db.SaveChanges();

متعلق ب AddOrUpdate, أعتقد أن هناك قضية مفتوحة يمكن العثور عليها هنا.

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