मुझे MVC3 में कोड फर्स्ट एंटिटी फ्रेमवर्क (4.1) का उपयोग करके विदेशी कुंजी संबंधों की घोषणा कैसे करनी चाहिए?


104

मैं संसाधनों के बारे में खोज रहा हूं कि कैसे विदेशी किस्मत के रिश्तों और अन्य बाधाओं को घोषित करने के लिए कोड का उपयोग कर ईएफ 4.1 का उपयोग बहुत अधिक भाग्य के बिना किया जाता है। मूल रूप से मैं कोड में डेटा मॉडल का निर्माण कर रहा हूं और उस मॉडल को क्वेरी करने के लिए MVC3 का उपयोग कर रहा हूं। सब कुछ MVC के माध्यम से काम करता है जो महान है (माइक्रोसॉफ्ट के लिए यश!) लेकिन अब मैं चाहता हूं कि यह काम न करे क्योंकि मुझे डेटा मॉडल की कमी है।

उदाहरण के लिए, मेरे पास एक ऑर्डर ऑब्जेक्ट है जिसमें एक टन गुण हैं जो बाहरी ऑब्जेक्ट (टेबल) हैं। अभी मैं ऑर्डर की कोई समस्या नहीं बना सकता, लेकिन विदेशी कुंजी या बाहरी वस्तुओं को जोड़ने में सक्षम हुए बिना। MVC3 सेट करता है यह कोई समस्या नहीं है।

मुझे एहसास है कि मैं ऑब्जेक्ट्स को सहेजने से पहले कंट्रोलर क्लास में खुद को जोड़ सकता हूं, लेकिन मैं चाहूंगा कि DbContext.SaveChanges () को विफल कर दिया जाए, अगर बाधा के रिश्तों को पूरा नहीं किया गया है।

नई जानकारी

इसलिए, विशेष रूप से, मैं तब अपवाद होना चाहूंगा जब मैं ग्राहक वस्तु को निर्दिष्ट किए बिना ऑर्डर ऑब्जेक्ट को सहेजने का प्रयास करूंगा। यह व्यवहार प्रतीत नहीं होता है यदि मैं ऑब्जेक्ट्स को सबसे अधिक कोड फर्स्ट ईएफ प्रलेखन में वर्णित करता हूं।

नवीनतम कोड:

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

    [ForeignKey( "Parent" )]
    public Patient Patient { get; set; }

    [ForeignKey("CertificationPeriod")]
    public CertificationPeriod CertificationPeriod { get; set; }

    [ForeignKey("Agency")]
    public Agency Agency { get; set; }

    [ForeignKey("Diagnosis")]
    public Diagnosis PrimaryDiagnosis { get; set; }

    [ForeignKey("OrderApprovalStatus")]
    public OrderApprovalStatus ApprovalStatus { get; set; }

    [ForeignKey("User")]
    public User User { get; set; }

    [ForeignKey("User")]
    public User Submitter { get; set; }

    public DateTime ApprovalDate { get; set; }
    public DateTime SubmittedDate { get; set; }
    public Boolean IsDeprecated { get; set; }
}

यह वह त्रुटि है जो अब मुझे मिलती है जब रोगी के लिए वी.एस.

त्रुटि संदेश

'PhysiPortal.Models.Order' प्रकार पर संपत्ति 'रोगी' पर ForeignKeyAttribute मान्य नहीं है। आश्रित प्रकार 'PhysicianPortal.Models.Order' पर विदेशी कुंजी नाम 'जनक' नहीं मिला। नाम मान विदेशी प्रमुख संपत्ति नामों की अल्पविराम से अलग की गई सूची होनी चाहिए।

सादर,

गुइडो

जवाबों:


164

यदि आपके पास एक Orderवर्ग है, तो एक संपत्ति जोड़ना जो आपके मॉडल में किसी अन्य वर्ग को संदर्भित करता है, उदाहरण के Customerलिए ईएफ को यह बताने के लिए पर्याप्त होना चाहिए कि इसमें कोई संबंध है:

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    public virtual Customer Customer { get; set; }
}

आप हमेशा FKस्पष्ट रूप से संबंध निर्धारित कर सकते हैं :

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    [ForeignKey("Customer")]
    public string CustomerID { get; set; }
    public virtual Customer Customer { get; set; }
}

ForeignKeyAttributeनिर्माता एक पैरामीटर के रूप में एक स्ट्रिंग लेता है: यदि आप एक विदेशी कुंजी संपत्ति पर रखें यह संबद्ध नेविगेशन गुण का नाम का प्रतिनिधित्व करता है। यदि आप इसे नेविगेशन प्रॉपर्टी पर रखते हैं तो यह संबंधित विदेशी कुंजी के नाम का प्रतिनिधित्व करता है।

इसका मतलब क्या है, यदि आप संपत्ति ForeignKeyAttributeपर जगह देना Customerचाहते हैं CustomerID, तो निर्माणकर्ता में विशेषता होगी :

public string CustomerID { get; set; }
[ForeignKey("CustomerID")]
public virtual Customer Customer { get; set; }

नवीनतम कोड के आधार पर EDIT आपको इस लाइन के कारण वह त्रुटि मिलती है:

[ForeignKey("Parent")]
public Patient Patient { get; set; }

ईएफ एक संपत्ति की तलाश करेगा जिसे Parentविदेशी कुंजी प्रवर्तक के रूप में उपयोग करने के लिए कहा जाता है। आप 2 काम कर सकते हैं:

1) आवश्यक के रूप में संबंध को चिह्नित करने ForeignKeyAttributeके RequiredAttributeलिए इसे निकालें और इसे बदलें :

[Required]
public virtual Patient Patient { get; set; }

प्रॉपर्टी को सजाने RequiredAttributeका एक अच्छा साइड इफेक्ट भी है: डेटाबेस में रिलेशन का निर्माण होता है ON DELETE CASCADE

मैं virtualआलसी लोडिंग को सक्षम करने के लिए संपत्ति बनाने की भी सिफारिश करूंगा ।

2) एक प्रॉपर्टी बनाएं जिसे Parentफॉरेन की के रूप में काम करेंगे। उस स्थिति में संभवतः इसे उदाहरण के लिए कॉल करने के लिए अधिक समझ में आता है ParentID(आपको नाम को भी बदलने की आवश्यकता होगी ForeignKeyAttribute):

public int ParentID { get; set; }

इस मामले में मेरे अनुभव में हालांकि यह बेहतर है कि इसे दूसरे तरीके से किया जाए:

[ForeignKey("Patient")]
public int ParentID { get; set; }

public virtual Patient Patient { get; set; }

धन्यवाद सर्गी - मैंने ब्लॉक उद्धरण में कुछ अतिरिक्त जानकारी जोड़ी।
गुइडो एंसेलमी

@ ग्यूइडो - मैंने अपना उत्तर आपके नवीनतम कोड एडिट में आधारित अपडेट किया है, आशा है कि इससे मदद मिलेगी।
सेर्गी पपसीत

30

आप इसके द्वारा विदेशी कुंजी परिभाषित कर सकते हैं:

public class Parent
{
   public int Id { get; set; }
   public virtual ICollection<Child> Childs { get; set; }
}

public class Child
{
   public int Id { get; set; }
   // This will be recognized as FK by NavigationPropertyNameForeignKeyDiscoveryConvention
   public int ParentId { get; set; } 
   public virtual Parent Parent { get; set; }
}

अब पेरेंटआईड विदेशी संपत्ति है और बच्चे और मौजूदा माता-पिता के बीच आवश्यक संबंध को परिभाषित करता है। माता-पिता से बाहर निकले बिना बच्चे को बचाना अपवाद को फेंक देगा।

यदि आपके FK प्रॉपर्टी के नाम में नेविगेशन प्रॉपर्टी का नाम और माता-पिता का पीके नाम शामिल नहीं है, तो आपको संबंध को मैप करने के लिए ForeignKeyAttribute डेटा एनोटेशन या धाराप्रवाह API का उपयोग करना होगा।

डेटा एनोटेशन:

// The name of related navigation property
[ForeignKey("Parent")]
public int ParentId { get; set; }

धाराप्रवाह एपीआई:

modelBuilder.Entity<Child>()
            .HasRequired(c => c.Parent)
            .WithMany(p => p.Childs)
            .HasForeignKey(c => c.ParentId);

अन्य प्रकार की बाधाओं को डेटा एनोटेशन और मॉडल सत्यापन द्वारा लागू किया जा सकता है ।

संपादित करें:

यदि आप सेट नहीं करते हैं तो आपको एक अपवाद मिलेगा ParentId। यह आवश्यक है संपत्ति (अशक्त नहीं)। यदि आप इसे सेट नहीं करते हैं, तो यह संभवतः डेटाबेस में डिफ़ॉल्ट मान भेजने का प्रयास करेगा। डिफ़ॉल्ट मान 0 है इसलिए यदि आपके पास Id = 0 के साथ ग्राहक नहीं है, तो आपको एक अपवाद मिलेगा।


धन्यवाद लदिस्लाव - मैंने ब्लॉक उद्धरण में कुछ अतिरिक्त जानकारी जोड़ी।
गुइडो एंसेलमी

@Ladislav। तो इस बाधा को लागू करने के लिए, मेरे पास माता-पिता का संदर्भ और ParentId का संदर्भ होना चाहिए। क्या वो सही है? मैं संदर्भ के लिए ऊपर वास्तविक वर्ग जोड़ूंगा।
गुइडो एंसेलमी

@ गुइडो: यह नई जानकारी है। आप विदेशी कुंजी गुणों का उपयोग नहीं कर रहे हैं। डिफ़ॉल्ट रूप से आपके सभी नेविगेशन गुणों को वैकल्पिक रूप में नियंत्रित किया जाता है। आवश्यकतानुसार उन्हें मैप करने के लिए धाराप्रवाह मानचित्रण का उपयोग करें।
लादिस्लाव मृका

@ लादिस्लाव: फिर से धन्यवाद। मैं डेटा एनोटेशन और धाराप्रवाह एपीआई का उपयोग करने के बीच के अंतर को समझने के लिए चारों ओर देख रहा हूं। मैंने जो आप कह रहे हैं, उसके अनुरूप मैंने ऊपर दिए गए कोड में बदलाव किए। क्या उपरोक्त सभी मुझे करना है? सादर।
गुइडो एंसेलमी

कोई फॉरेनकेई विशेषता विदेशी कुंजी संपत्ति या इसके विपरीत से संबंधित नेविगेशन संपत्ति को परिभाषित नहीं करती है। आपके पास विदेशी कुंजी गुण नहीं हैं, इसलिए आप उस विशेषता का उपयोग नहीं कर सकते। अपने नेविगेशन गुणों पर आवश्यक विशेषता का उपयोग करने का प्रयास करें (मैंने इसका परीक्षण नहीं किया है)।
लादिस्लाव मृका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.