رابط للكيانات:رسم بياني مختلط للكيانات ومفاتيح الكيانات والكائنات المرفقة والجديدة

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

سؤال

في نموذج البيانات الخاص بي، لدي تقسيم شائع إلى حد ما بين الكائنات/الجداول/البيانات الخاصة بي:

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

لذلك، على سبيل المثال، قد يكون لدي كيان مستخدم (المعاملات) وكيان UserType (قاموس البيانات).

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

أنا أستخدم LINQ-to-Entities كتقنية/ORM للوصول إلى البيانات الخاصة بي.لتنفيذ مراجع قاموس البيانات، أقوم بتخزين EntityKeys.ما أفهمه هو أنها منفصلة عن سياق الكائن وبالتالي فهي مناسبة لهذا الغرض.(نظرًا لأنها لا تحتوي على حالة كيان، فلا داعي للقلق أيضًا بشأن تقادم هذه الحالة.)

ومع ذلك، فإن هذا يسبب لي مشاكل عندما أحاول إضافة كيان معاملات جديد باستخدام مرجع DD-EntityKey.استمرارًا لمثالي، أفعل هذا:

UserEntities userEntities = new UserEntitites()
User user = new User()
user.UserType = new UserType()
user.UserType.EntityKey = adminEntityKey
userEntities.AddToUser(user)

.. وهذا يعطيني الخطأ التالي:

System.InvalidOperationException :لا يمكن إضافة الكائن إلى ObjectStateManager لأنه يحتوي بالفعل على EntityKey.استخدم ObjectContext.Attach لإرفاق كائن يحتوي على مفتاح موجود.

إذا حاولت الاتصال بـ userEntities.Attach(user) بدلاً من AddToUser، أحصل على هذا:

System.InvalidOperationException :لا يمكن إرفاق كائن بقيمة EntityKey فارغة بسياق كائن.

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

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

المحلول

سأحاول شرح سبب حصولك على هذه الاستثناءات:

System.InvalidOperationException :لا يمكن إضافة الكائن إلى ObjectStateManager لأنه يحتوي بالفعل على EntityKey.استخدم ObjectContext.Attach لإرفاق كائن يحتوي على مفتاح موجود.

يتم إنشاء كيانات المستخدم وUserType الجديدة.تم تعيين EntityKey على UserType ولكن عندما تقوم بتمريره إلى userEntities.Add() EF تحاول تعيين الحالة "مضافة".نظرًا لأن UserType لديه EntityKey EF، يدرك أن هناك خطأ ما ويطرح استثناءً.

System.InvalidOperationException :لا يمكن إرفاق كائن بقيمة EntityKey فارغة بسياق كائن.

في هذا الاستثناء، كل شيء على ما يرام مع UserType، ولكن تم طرح الاستثناء لأن كيان المستخدم - لا يحتوي على EntityKey وبالتالي لا يمكن إرفاقه.

هذه هي الطريقة التي سأحل بها هذه المشكلة (إذا، كما تقول، كان الترميز الثابت لمراجع قاموس البيانات على ما يرام):

في كيان UserType سأقوم بإنشاء مراجع ثابتة لمعرفات UserType:

public partial class UserType
    {
        public const int AdminUserTypeID = 1;
        public const int PlainUserTypeID = 2;
    }  

في كيان المستخدم ستكون هناك خاصية موسع لتسهيل الوصول إلى المفتاح الخارجي UserType:

public partial class User
{
    public int? UserTypeID
    {
        set
        {
           UserTypeReference.EntityKey = new EntityKey("UserEntities.UserType", "UserTypeID", value);
        }
        get
        {
            if (UserTypeReference.EntityKey == null)
                return null;

            if (UserTypeReference.EntityKey.EntityKeyValues.Count() > 0)
                return (int)UserTypeReference.EntityKey.EntityKeyValues[0].Value;
            else
                return null;
        }
    }
}

وأخيرًا، ستبدو حالة الاستخدام لإنشاء مستخدم جديد كما يلي:

using(UserEntities userEntities = new UserEntitites())
{
    User user = new User();
    user.UserTypeID = UserType.AdminUserTypeID;
    userEntities.AddToUser(user);
    userEntities.SaveChanges()
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top