2011-04-04 3 views
86

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

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

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

नई जानकारी

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

नवीनतम कोड:

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

यह वह जगह है त्रुटि मैं अब मिल जब तक पहुँचने वी.एस. रोगी के लिए दृश्य उत्पन्न: संपत्ति पर

त्रुटि संदेश

ForeignKeyAttribute ' रोगी 'प्रकार ' चिकित्सक पोर्टल.मोडल्स.ऑर्डर ' मान्य नहीं है। विदेशी कुंजी नाम 'अभिभावक' आश्रित प्रकार 'चिकित्सक पोर्टल.मोडल्स.ऑर्डर' पर नहीं मिला था। नाम मान विदेशी कुंजी संपत्ति नामों की सूची को अल्पविराम से अलग किया जाना चाहिए।

सादर,

गुइडो

उत्तर

146

आप एक 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 कन्स्ट्रक्टर पैरामीटर के रूप में एक स्ट्रिंग लेता है: यदि आप इसे विदेशी कुंजी प्रॉपर्टी पर रखते हैं तो यह संबंधित नेविगेशन प्रॉपर्टी के नाम का प्रतिनिधित्व करता है। यदि आप इसे नेविगेशन प्रॉपर्टी पर रखते हैं तो यह संबंधित विदेशी कुंजी के नाम का प्रतिनिधित्व करता है।

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

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

संपादित करें आपको इस पंक्ति के कारण यह त्रुटि मिलती है:

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

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

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

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

RequiredAttribute के साथ एक संपत्ति सजा भी एक अच्छा पक्ष प्रभाव पड़ता है: संबंध आप 2 कर सकते हैं डेटाबेस में ON DELETE CASCADE के साथ बनाया गया है।

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

2) Parent नामक एक संपत्ति बनाएं जो विदेशी कुंजी के रूप में कार्य करेगी। हालांकि यह बेहतर काम करता है यह है करने के लिए इस मामले में

public int ParentID { get; set; } 

मेरे अनुभव में: उस मामले यह शायद यह उदाहरण ParentID के लिए कॉल करने के लिए और अधिक समझ में आता है में (आप ForeignKeyAttribute में नाम बदलने के लिए और साथ ही आवश्यकता होगी) दूसरी तरह के आसपास:

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

public virtual Patient Patient { get; set; } 
+0

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

+0

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

+1

अच्छी तरह से Sergi किया! – Shimmy

27

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

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

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

अपने FK संपत्ति नाम नेविगेशन संपत्ति नाम और माता पिता पीके नाम आप या तो ForeignKeyAttribute डेटा एनोटेशन या धाराप्रवाह एपीआई का उपयोग करना चाहिए संबंध

डाटा एनोटेशन मैप करने के लिए होते हैं नहीं होता है:

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

की कमी के अन्य प्रकार data annotations and model validation द्वारा लागू किया जा सकता है।

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

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

+0

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

+0

@ गुइडो: मेरा जवाब संपादित किया। –

+0

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