كيفية الإعلان عن علاقة فردية باستخدام Entity Framework 4 Code First (POCO)

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

سؤال

كيف يتم الإعلان عن علاقة رأس برأس باستخدام Entity Framework 4 Code First (POCO)؟

وجدت هذا السؤال (العلاقات الفردية في Entity Framework 4) , ، لكن المقالة التي تشير إليها الإجابة لم تكن مفيدة (يوجد سطر واحد من التعليمات البرمجية يمثل علاقة 1-1، ولكن لا يوجد ذكر لكيفية تعريفه).

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

المحلول

هل تبحث فقط عن شيء مثل هذا؟

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public Profile Profile { get; set; }
    public int ProfileId { get; set; }
}

public class Profile
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PostalCode { get; set; }
    // etc...
}

public class UserMapping : EntityConfiguration<User>
{
    public UserMapping()
    {
        this.HasKey(u => u.Id);
        this.Property(u => u.Username).HasMaxLength(32);

        // User has ONE profile.
        this.HasRequired(u => u.Profile);
    }
}

public class ProfileMapping : EntityConfiguration<Profile>
{
    public ProfileMapping()
    {
        this.HasKey(p => p.Id);
        this.Property(p => p.FirstName).HasMaxLength(32);
        this.Property(p => p.LastName).HasMaxLength(32);
        this.Property(p => p.PostalCode).HasMaxLength(6);
    }
}

تعديل: نعم لم يكن لدي مقابل أمامي ولكن عليك إضافة السطر التالي في UserMapping بدلا من التيار HasRequired وأضف أيضا أ ProfileId خاصية (بدلا من Profile_Id التي أضفتها):

this.HasRequired(u => u.Profile).HasConstraint((u, p) => u.ProfileId == p.Id);

لا أعتقد حاليًا أن هناك طريقة للتغلب على هذا ، لكنني متأكد من أنها ستتغير لأننا فقط في CTP4. سيكون من الرائع أن أقول:

this.HasRequired(u => u.Profile).WithSingle().Map(
    new StoreForeignKeyName("ProfileId"));

بهذه الطريقة لن أضطر إلى تضمين أ ProfileId منشأه. ربما هناك طريقة للتغلب على هذا الوقت حاليًا وما زالت في الصباح الباكر لأفكر :).

تذكر أيضًا الاتصال .Include("Profile") إذا كنت ترغب في تضمين "خاصية ملاحية".

نصائح أخرى

ثلاث طرق:

أ) قم بتعريف كلا الفئتين بخصائص التنقل لبعضهما البعض.قم بوضع علامة على أحد الجداول (الجدول التابع) باستخدام سمة ExternalKey على مفتاحه الأساسي.تستنتج EF 1 إلى 1 من هذا:

public class AppUser
{
    public int Id { get; set; }

    public string Username { get; set; }

    public OpenIdInfo OpenIdInfo { get; set; }
}

​public class OpenIdInfo
{
    [ForeignKey("AppUser")]
    public int Id { get; set; }

    public string OpenId { get; set; }

    public AppUser AppUser { get; set; }
}

http://weblogs.asp.net/manavi/archive/2011/05/01/associations-in-ef-4-1-code-first-part-5-one-to-one-foreign-key-associations. com.aspx

لم أستخدم virtual ولا ينبغي لك ذلك أيضًا.*

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

using System.ComponentModel.DataAnnotations;

[Table("AppUser")]
public class AppUser
{
    public int Id { get; set; }

    public string Username { get; set; }

    public OpenIdInfo OpenIdInfo { get; set; }
}

[Table("AdminUser")]      
public class AdminUser : AppUser
{
    public bool SuperAdmin { get; set; }
}

سوف تحصل على جدولين:واحد لمستخدم التطبيق، والآخر لـ AdminUser.AdminUser هو 1:1 مع AppUser وهو تابع - مما يعني أنه يمكنك حذف AdminUser، ولكن إذا قمت بحذف AppUser عندما لا يزال AdminUser يشير إليه، فسوف تحصل على خطأ انتهاك القيد.​

ج) هناك طريقتان في منتصف الطريق للقيام بواحد لواحد في EF:

تقسيم الكيان, ، حيث يكون لديك فصل دراسي واحد، ولكن يتم تخزينه في جدول أساسي، وجدول واحد أو أكثر مرتبطين بواحد لواحد.

تقسيم الجدول, ، حيث يتم تسوية شجرة الكائنات في جدول واحد.على سبيل المثال، قد تحتوي فئة ذات خاصية عنوان على أعمدة لكائن العنوان، مثل Address_City، ومسطحة في جدول واحد.

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

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }

    public virtual Profile Profile { get; set; }
}

public class Profile
{
    public int Id { get; set; }

    public int UserID { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PostalCode { get; set; }
}

أضف ملف التعريف الافتراضي و userId وأعتقد أنه يجب أن يحصل على هناك.

خذ مثالًا على كيانات الطالب والطالب التالية.
تكوين علاقة منفردة أو واحدة باستخدام DataAntations:

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    [ForeignKey("Student")]
    public int StudentAddressId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

عندما لا يتبع كيان NatureDdress الاتفاقيات:

على سبيل المثال ، إذا لم يتبع كيان StudentAddress اتفاقية PK IE اسم مختلف لخاصية المعرف ، فأنت بحاجة إلى تكوينه لـ PK أيضًا. ضع في اعتبارك كيان StudentAddress التالي الذي يحتوي على اسم الممتلكات StudentId بدلاً من StudentAddressId.

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    [Key, ForeignKey("Student")]
    public int StudentId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

في المثال أعلاه ، نحتاج إلى تكوين خاصية StudentId كمفتاح وكذلك ForeignKey. سيؤدي ذلك إلى جعل الممتلكات الطلابية في كيان StudentAddress مثل PK و FK على حد سواء.

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

يحدد المثال التالي علاقة واحدة أو صفرًا أو علاقة واحدة بين الطالب والطالب باستخدام واجهة برمجة التطبيقات بطلاقة.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{

    // Configure Student & StudentAddress entity
    modelBuilder.Entity<Student>()
                .HasOptional(s => s.Address) // Mark Address property optional in Student entity
                .WithRequired(ad => ad.Student); // mark Student property as required in StudentAddress entity. Cannot save StudentAddress without Student

}

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

وبالتالي ، يمكنك تكوين علاقة من فرد أو صفر أو واحد بين كيانين حيث يمكن حفظ كيان الطالب دون إرفاق كائن StudentAddress به ولكن لا يمكن حفظ كيان StudentAddress دون إرفاق كائن من كيان الطالب. هذا يجعل نهاية واحدة مطلوبة.

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

public class Student
{
    public Student() { }

    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }

}

public class StudentAddress 
{
    public int StudentId { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

حتى الآن ، نحتاج إلى تكوين خاصية StudentId من StudentAddress لـ PrimaryKey of StudentAddress وكذلك ForeignKey كما هو موضح أدناه.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as PK for StudentAddress
    modelBuilder.Entity<StudentAddress>()
        .HasKey(e => e.StudentId);

    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity<Student>()
                .HasOptional(s => s.Address) 
                .WithRequired(ad => ad.Student); 

}

تكوين علاقة فردية باستخدام واجهة برمجة التطبيقات بطلاقة:
يمكننا تكوين علاقة فردية بين الكيانات التي تستخدم واجهة برمجة تطبيقات بطلاقة حيث يكون كلا الطرفين مطلوبًا ، مما يعني أن كائن كيان الطالب يجب أن يتضمن كائن كيان StudentAddress ويجب أن يتضمن كيان الطالب كائن كيان الطالب من أجل حفظه.

ملاحظة: علاقة فردية غير ممكنة تقنيًا في خادم MS SQL. سيكون دائما واحد إلى الصفر أو واحد. تشكل EF علاقات فردية على الكيانات وليس في DB.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as PK for StudentAddress
    modelBuilder.Entity<StudentAddress>()
        .HasKey(e => e.StudentId);

    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity<Student>()
                .HasRequired(s => s.Address) 
                .WithRequiredPrincipal(ad => ad.Student); 

}

في المثال أعلاه ، ModelBuilder.Entity (). hasrequired (s => s.address) يجعل خاصية addrent of studentaddress مطلوبة. . withrequiredprincipal (ad => ad.student) يجعل ممتلكات الطالب من كيان studentAddress كما هو مطلوب. وبالتالي فإنه يهيئ كلا الطرفين المطلوب. حتى الآن ، عندما تحاول حفظ كيان الطالب بدون عنوان أو كيان StudentAddress بدون طالب ، فإنه سوف يلقي استثناءً.

المرجعي :http://www.entityframeworktutorial.net/code-first/configure-one-to---relationship-in-code-first.aspx

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