لماذا هي مجموعة بروكسي Frantity Framework First Null ولماذا لا يمكنني تعيينها؟

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

سؤال

أنا أستخدم DBContext ولدي فئتان تكون خصائصهما كلها افتراضية. أستطيع أن أرى في The Debugger أنني أحصل على كائن وكيل عندما أستفسر عن السياق. ومع ذلك ، لا تزال خاصية التجميع لاغية عندما أحاول إضافتها. اعتقدت أن الوكيل سيضمن تهيئة التجميع.

نظرًا لأنه يمكن استخدام كائن POCO الخاص بي خارج سياق البيانات الخاص به ، فقد أضفت فحصًا للمجموعة خالية من المُنشئ وإنشائها إذا لزم الأمر:

public class DanceStyle
{
    public DanceStyle()
    {
        if (DanceEvents == null)
        {
            DanceEvents = new Collection<DanceEvent>();
        }
    }
    ...
    public virtual ICollection<DanceEvent> DanceEvents { get; set; }
}

يعمل هذا خارج سياق البيانات ، لكن إذا قمت باسترداد كائن باستخدام استعلام ، على الرغم من أن الاختبار صحيح ، عندما أحاول تعيينه ، أحصل على استثناء متابع: "خاصية" الرقص "على النوع 'Dancestyle_B6089ae40d1785939555f1328a70eaa3d8f01dde9f9fbd615f60a341f60a3418419f9417417417417417417417415f60a34. تم تعيين المجموعة بالفعل على EntityCollection.

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

ها هو فئة الرقص:

public class DanceEvent
{
    public DanceEvent()
    {
        if (DanceStyles == null)
        {
            DanceStyles = new Collection<DanceStyle>();
        }
    }
    ...
    public virtual ICollection<DanceStyle> DanceStyles { get; set; }
}

لقد حذفت خصائص القيمة الأخرى من الكود أعلاه. ليس لدي تعيينات أخرى لتلك الفصول في فئة السياق.

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

المحلول 2

لقد وجدت الحل لهذه المشكلة هنا: رمز الإضافة أولاً إلى المجموعات؟ كيفية استخدام التعليمات البرمجية أولاً مع المستودعات؟

لقد أزلت "افتراضية" من جميع الخصائص باستثناء المجموعات والكائنات المحملة كسول ، أي جميع الأنواع الأصلية.

لكنني ما زلت لا أفهم كيف يمكنك أن ينتهي بك الأمر بالموقف الذي لديك مجموعة فارغة لا يمكنك استخدامها وليس لديك طريقة لتعيينها على مجموعة صالحة.

لقد وجدت أيضا هذه الإجابة من روان ميلر في منتدى MSDN

أهلاً،

إذا قمت بعمل جميع خصائصك افتراضية ، فستقوم EF بإنشاء فئات وكيل في وقت التشغيل المستمدة من تصنيف POCO الخاص بك ، فإن هذه الوكلاء تسمح لـ EF بمعرفة التغييرات في الوقت الفعلي بدلاً من الاضطرار إلى التقاط القيم الأصلية لكائنك ومن ثم المسح الضوئي للتغييرات عندما تنقذ (من الواضح أن هذا لديه فوائد استخدام الأداء والذاكرة ولكن الفرق سيكون ضئيلًا ما لم يكن لديك عدد كبير من الكيانات المحملة في الذاكرة). تُعرف هذه باسم "تغيير وكلاء تتبع" ، إذا قمت بتجميع خصائص التنقل الخاصة بك ، فلا يزال يتم إنشاء وكيل ولكنه أبسط بكثير ويتضمن بعض المنطق لأداء التحميل كسول عند الوصول إلى خاصية التنقل.

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

ما لم تشاهد مشكلات في الأداء ، فسأتبع اقتراح تيرينس وإزالة "الظاهري" فقط من خصائص عدم التأهيل.

~ روان

لذلك يبدو أنني أواجه مشكلة فقط في "Proxy Tracking Proxy" الكامل إذا كانت جميع خصائصي افتراضية. ولكن بالنظر إلى ذلك ، لماذا لا يزال بإمكاني عدم استخدام الخاصية الافتراضية في وكيل تتبع التغيير؟ ينفجر هذا الرمز على السطر الثالث لأن ds2.danceevents فارغ ولا يمكن تعيينه في المُنشئ:

DanceStyle ds2 = ctx.DanceStyles.Where(ds => ds.DanceStyleId == 1).Single();
DanceEvent evt = CreateDanceEvent();
ds2.DanceEvents.Add(evt);

ما زلت مرتبكًا ، على الرغم من أن الكود الخاص بي يعمل الآن بسبب الإصلاح أعلاه.

نصائح أخرى

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

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

public class DanceEvent
{
    private ICollection<DanceStyle> _danceStyles;
    public virtual ICollection<DanceStyle> DanceStyles
    {
        get { return _danceStyles ?? (_danceStyles = new Collection<DanceStyle>()); }
        protected set { _danceStyles = value; }
    }
}

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

سؤال قديم ...

فئة بوكو:

public partial class MyPOCO
{
    public MyPOCO()
    {
        this.MyPocoSub = new HashSet<MyPocoSub>();
    }

    //VIRTUAL
    public virtual ICollection<MyPocoSub> MyPocoSub { get; set; }
}

ورمز الوكيل:

    public override ICollection<MyPocoSubSet> MyPocoSubSets
    {
        get
        {
            ICollection<MyPocoSubSet> myPocoSubSets = base.MyPocoSubSets;
            if (!this.ef_proxy_interceptorForMyPocoSubSets(this, myPocoSubSets))
            {
                return base.MyPocoSubSets;
            }
            return myPocoSubSets;
        }
        set
        {
            if (value != this.RelationshipManager.GetRelatedEnd("WindowsFormsApplication.Models.MyPocoSubSet_MyPOCO", "MyPocoSubSet_MyPOCO_Source"))
            {
                // EXCEPTION 
                throw new InvalidOperationException("The property 'MyPocoSubSets' on type 'MyPOCO_A78FCE6C6A890855C68B368B750864E3136B589F9023C7B1D90BF7C83FD291AC' cannot be set because the collection is already set to an EntityCollection.");
            }
            base.MyPocoSubSets = value;
        }
    }

كما ترون أن الاستثناء أثير في فئة الوكيل في ExtityFramework 5. هذا يعني أن السلوك لا يزال موجودًا.

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