2010-09-01 14 views
12

का उपयोग करके एक से एक रिश्ते की घोषणा कैसे करें Entity Framework 4 Code First (POCO) का उपयोग करके एक से एक रिश्ते को कैसे घोषित करें?एंटिटी फ्रेमवर्क 4 कोड फर्स्ट (पीओसीओ)

मुझे this question (one-to-one relationships in Entity Framework 4) मिला, लेकिन लेख जो उत्तर संदर्भ उपयोगी नहीं था (कोड की एक पंक्ति है जो 1-1 रिश्ते है, लेकिन इसे परिभाषित करने का कोई उल्लेख नहीं है)।

उत्तर

11

क्या आप इस तरह कुछ ढूंढ रहे हैं?

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); 
    } 
} 

संपादित: हाँ मैं मेरे सामने वी.एस. नहीं था, लेकिन आप वर्तमान HasRequired के बजाय UserMapping में निम्न पंक्ति जोड़ने के लिए और भी (Profile_Id के बजाय एक ProfileId संपत्ति जोड़ने की जरूरत है कि आप जोड़ा):

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") पर भी कॉल करना याद रखें।

+0

क्या यह आपके लिए काम करता है? मैं इसे काम नहीं कर सकता। मैं डेटाबेस को स्वचालित रूप से उत्पन्न नहीं कर रहा हूं क्योंकि मेरे पास मौजूदा टेबल हैं। मेरी प्रोफाइल तालिका में आईडी को पीके और एफके के रूप में है (क्योंकि रिश्ते 1: 1 है)। मैं इसे लेता हूं कि यह आपके जैसा ही है। यदि मैं अपना कोड आज़माता हूं और चलाता हूं, तो मुझे एक त्रुटि मिलती है: अमान्य कॉलम नाम 'Profile_Id'। यदि मैं उस कॉलम को उपयोगकर्ता में जोड़ता हूं (नहीं कि मैं इसे वहां चाहता हूं), उपयोगकर्ता वापस आ गया है लेकिन प्रोफ़ाइल शून्य है। उत्पन्न एसक्यूएल है:। चयन [Extent1] [ईद] के रूप में [ID], [Extent1] [प्रयोक्ता नाम] के रूप में [उपयोगकर्ता नाम], [Extent1] [PROFILE_ID] के रूप में [PROFILE_ID] [dbo से।। ]। [उपयोगकर्ता] एएस [विस्तार 1] कोई विचार? –

+0

हम्म। दूसरे निरीक्षण पर, ऐसा लगता है कि यह sqlce4 पर ठीक काम करता है, लेकिन SQL सर्वर 2010 तक नहीं जब तक कि मुझे कुछ याद नहीं आ रहा है। –

+1

@ zaph0d - अगर आप "किसी अन्य इकाई" की संपत्ति तक पहुंचना चाहते हैं, तो आपको इसे "शामिल" करने की आवश्यकता है। ऐसा करने का तरीका 'संदर्भ' होगा। उपयोगकर्ता शामिल करें ("प्रोफ़ाइल") '। प्रोफ़ाइल एक "नेविगेशन संपत्ति" है जिसे SQL में जॉइन की आवश्यकता होगी। मैंने अपनी पोस्ट को अतिरिक्त जानकारी के साथ संपादित किया है जिसे मैं प्रोफ़ाइल के लिए भूल गया था। – TheCloudlessSky

1
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; } 
} 

वर्चुअल प्रोफाइल और उपयोगकर्ता आईडी जोड़ें और मुझे लगता है कि आपको वहां ले जाना चाहिए।

+2

क्या यह कई रिश्तों में से एक नहीं होगा? प्रश्न लगभग 1: 1 था। – saille

+0

नहीं, यह नहीं है। यह 1: 1 उपयोगकर्ता के पास इस उदाहरण में 1 प्रोफ़ाइल है ... यदि नहीं, तो मैंने पूरी तरह से कुछ गलत समझा है। – BjarkeCK

22

तीन तरीके:

ए) एक दूसरे के लिए नेविगेशन गुणों के साथ दोनों वर्गों घोषित। अपनी प्राथमिक कुंजी पर विदेशीकी विशेषता के साथ तालिकाओं में से एक (निर्भर तालिका) को चिह्नित करें। एफई 1 से 1 इस से infers:।

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.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; } 
} 

आपको 2 टेबल मिलेगा: AppUser के लिए एक, AdminUser के लिए एक। AdminUser AppUser के साथ 1: 1 है और आश्रित है - जिसका अर्थ है कि आप एक AdminUser को हटा सकते हैं, लेकिन यदि आप कोई ऐपयूसर हटाते हैं, तो जब कोई AdminUser अभी भी इंगित कर रहा है, तो आपको एक बाधा उल्लंघन त्रुटि मिल जाएगी।

सी) वहाँ 2 एक-से-एक एफई में करने का आधे रास्ते तरीके हैं:

Entity-Splitting, जहां आप एक ही क्लास है, लेकिन यह एक प्राथमिक तालिका में संग्रहीत है, और 1 या अधिक एक से एक संबंधित टेबल।

Table-Splitting, जहां ऑब्जेक्ट का एक पेड़ एक ही टेबल में फैला हुआ है। उदाहरण के लिए एक पता संपत्ति वाले वर्ग में एड्रेस ऑब्जेक्ट के लिए कॉलम होंगे, जैसे पता_City, एक ही टेबल में फ़्लैट किया गया है।

* आप किसी भी ईएफ संपत्ति या संग्रह if you want to lazy-load them पर आभासी शामिल कर सकते हैं। इसके परिणामस्वरूप अनंत लूप हो सकते हैं या पूरे डीबी को लोड कर सकते हैं यदि आप ऑब्जेक्ट को आलसी लोडेड गुणों के साथ पास करते हैं, उदाहरण के लिए, एमवीसी जेएसओएन कनवर्टर या ऑब्जेक्ट पदानुक्रम पर चलने वाली कोई और चीज। आलसी लोडिंग हमेशा सिंक्रनाइज़ किया जाता है, थ्रेड को अवरुद्ध करता है, और बिना किसी सूचना के। संक्षेप में, आपके कोड, ऐप या सर्वर को फ्रीज करने के तरीकों की सूची लंबी है। ईएफ कक्षाओं पर वर्चुअल का उपयोग करने से बचें। हां इंटरनेट पर बहुत से कोड नमूने हैं जो इसका इस्तेमाल करते हैं। नहीं, आपको अभी भी इसका उपयोग नहीं करना चाहिए।

+0

क्यों 'आभासी' कीवर्ड का उपयोग न करें – AminM

+0

@AminM आलसी लोडिंग और आभासी के अंत में नोट देखें। –

1

निम्नलिखित छात्र और छात्र एड्रेस इकाइयों का एक उदाहरण लें।
कॉन्फ़िगर एक-से-शून्य या एक संबंध का उपयोग कर DataAnnotations:

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; } 
} 

StudentAddress इकाई का पालन नहीं करता जब सम्मेलनों:

हैं, उदाहरण के लिए, StudentAddress इकाई का पालन नहीं करता पीके के लिए सम्मेलन यानी आईडी संपत्ति के लिए अलग-अलग नाम तो आपको पीके के लिए इसे कॉन्फ़िगर करने की आवश्यकता है। निम्नलिखित छात्र एड्रेस इकाई पर विचार करें जिसमें StudentAddressId के बजाय संपत्ति का नाम StudentId है।

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 संपत्ति बना देगा।

कॉन्फ़िगर एक-से-शून्य या एक रिश्ते Fluent एपीआई का उपयोग कर:
जब छात्र और StudentAddress परंपराओं का पालन: छात्र और StudentAddress संस्थाओं PrimaryKey के लिए डिफ़ॉल्ट कोड-पहले सम्मेलन का पालन करें। इसलिए, हमें उनकी प्राथमिक कुंजी को परिभाषित करने के लिए उन्हें कॉन्फ़िगर करने की आवश्यकता नहीं है। हमें केवल छात्र एड्रेस इकाई को कॉन्फ़िगर करने की आवश्यकता है जहां 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() विधि जो इंगित करता है कि छात्र इकाई में StudentAddress नेविगेशन संपत्ति है का उपयोग कर कॉन्फ़िगर किया गया है एक वैकल्पिक (नहीं जब छात्र इकाई बचत आवश्यक)। फिर, WithRequired() विधि StudentAddress इकाई को कॉन्फ़िगर करती है और छात्र एड्रेस की छात्र नेविगेशन प्रॉपर्टी को आवश्यकतानुसार आवश्यक करती है (छात्र एड्रेस इकाई को सहेजते समय आवश्यक है। छात्र अपवाद संपत्ति छात्रवृत्ति इकाई के बिना सहेजने पर यह अपवाद फेंक देगा)। यह StudentAddressId को विदेशीकी के रूप में भी बना देगा।

इस प्रकार, आप दो इकाइयों के बीच एक-से-शून्य-या-एक रिश्ते को कॉन्फ़िगर कर सकते हैं जहां छात्र इकाई को छात्र एड्रेस ऑब्जेक्ट को अटैच किए बिना सहेजा जा सकता है लेकिन छात्र इकाई इकाई को छात्र इकाई के ऑब्जेक्ट को अटैच किए बिना सहेजा नहीं जा सकता है। यह एक अंत की आवश्यकता है।

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; } 
} 

तो अब, जैसा कि नीचे दिखाया StudentAddress की PrimaryKey के साथ-साथ ForeignKey के लिए StudentAddress की StudentId संपत्ति विन्यस्त करने की जरूरत।

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); 

} 

कॉन्फ़िगर एक-से-एक संबंध का उपयोग कर Fluent एपीआई:
हम Fluent एपीआई जहां दोनों सिरों के लिए आवश्यक हैं का उपयोग कर कॉन्फ़िगर कर सकते हैं संस्थाओं के बीच एक-से-एक संबंध है, जिसका अर्थ छात्र इकाई वस्तु StudentAddress इकाई में शामिल करना चाहिए ऑब्जेक्ट और छात्र एड्रेस इकाई में इसे सहेजने के लिए छात्र इकाई ऑब्जेक्ट को शामिल करना होगा।

नोट: एमएस एसक्यूएल सर्वर में एक-से-एक संबंध तकनीकी रूप से संभव नहीं है। यह हमेशा एक-से-शून्य या एक होगा। ईएफ संस्थाओं पर एक-से-एक रिश्तों को डीबी में नहीं बनाता है।

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.Address) बनाता है StudentAddress का पता संपत्ति की आवश्यकता है। .WithRequiredPrincipal (ad => ad.Student) छात्र एड्रेस इकाई की छात्र संपत्ति आवश्यकतानुसार बनाता है। इस प्रकार यह आवश्यक दोनों सिरों को विन्यस्त करता है। तो अब, जब आप विद्यार्थी के बिना छात्र इकाई को छात्र इकाई या छात्र एड्रेस इकाई को बचाने की कोशिश करते हैं, तो यह अपवाद फेंक देगा।

संदर्भ: http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

संबंधित मुद्दे