5

ऐसा लगता है कि ForeignKey विशेषता मेरे लिए काम नहीं कर रहा है मुझे लगता है, लेकिन मुझे लगता है मैं गलत उपयोग कर रहा हूँ लगता है;)इकाई की रूपरेखा कोड पहले विदेशी कुंजी मुद्दे

यह कोड के साथ व्याख्या करने के लिए आसान है:

public class BaseCard 
{ 
    public int Id {get ; set; } 
    public int BaseCardId { get; set; } 

    public List<Skill> Skills { get; set; } 
} 

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

    public int BaseCardId { get; set; } 
    [ForeignKey("BaseCardId")] 
    public BaseCard BaseCard { get; set; } 
} 

जब मैं बीज विधि के साथ इन वस्तुओं को भरने के लिए प्रयास करते हैं, मैं इस त्रुटि हो रही है:

INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.Skills_dbo.BaseCards_BaseCardId". The conflict occurred in database "Database", table "dbo.BaseCards", column 'Id'.

यह मेरे लिएमें ForeignKey की तरह लगता है 10 की कोशिश करता BaseCardId स्तंभ के बजाय BaseCards की Id स्तंभ पर बात करने के लिए, और मैं समझ नहीं क्यों ..

अगर मैं "सामान्य" IdBaseCard की संपत्ति हटाने, और के रूप में BaseCardId सेट करने का प्रयास पी, मैं निम्नलिखित त्रुटि मिलती है (विशेषता [Key] के साथ): के बजाय

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

किसी को भी पता है कि कैसे मैं काम करने के लिए तो संपत्ति BaseCardIdSkill वर्ग से BaseCard की BaseCardId संपत्ति को इंगित करेंगे इस कोड को प्राप्त कर सकते हैं स्पष्ट रूप से Id संपत्ति?

अग्रिम धन्यवाद!

+0

में कुछ उपयोगी कॉसीडरेशन देख सकते हैं क्यों आपके बेसकार्ड ऑब्जेक्ट में आईडी और बेसकार्ड आईडी फ़ील्ड हैं? – Sefa

+0

@vgSefa मैंने बेसकार्ड आईडी को एक निश्चित संख्या में सेट किया है। और आईडी, मैंने सोचा, स्वचालित रूप से जेनरेट किया गया था। लेकिन इसे एक विशिष्ट संख्या होने की जरूरत है। क्या आईडी को एक विशिष्ट संख्या में सेट करना संभव है? – Rob

+0

@vgSefa मैंने बेसकार्ड आईडी के बजाय आईडी को सेट करने की कोशिश की जो मुझे चाहिए, दुर्भाग्यवश यह काम नहीं करता .. – Rob

उत्तर

7

यह संभव है कि आप बेसकार्ड के आईडी को सेट कर सकें, लेकिन सबसे पहले आपको यह निर्दिष्ट करने के लिए Fluent Api का उपयोग करना होगा और एक से कई रिश्ते। साथ ही, इस तरह, आपको अपने मॉडल वर्गों में विशेषताओं को निर्दिष्ट करने की आवश्यकता नहीं है। आपका मॉडल वर्गों इस तरह होगा:

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

    public virtual ICollection<Skill> Skills { get; set; } 
} 

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

    public int BaseCardId { get; set; } 
    public virtual BaseCard BaseCard { get; set; } 
} 

आप देख सकते हैं, मैं virtual.If के रूप में आप आभासी एफई कार्यावधि में एक नया वर्ग (गतिशील प्रॉक्सी) पैदा करेगा के रूप में अपने नेविगेशन संपत्ति को परिभाषित नेविगेशन गुण से प्राप्त बदल अपनी बेसकार्ड कक्षा और इसके बजाय इसका उपयोग करें (कौशल के साथ भी ऐसा ही होता है)। इस नई गतिशील रूप से निर्मित कक्षा में पहली बार पहुंचने पर नेविगेशन प्रॉपर्टी लोड करने के लिए तर्क शामिल है। इस सुविधा को आलसी लोडिंग कहा जाता है। यह एंटीटी फ्रेमवर्क को सक्षम ऑब्जेक्ट्स के पूरे पेड़ को लोड करने से बचाने के लिए सक्षम करता है जिन्हें डेटाबेस से आवश्यक नहीं है। आप इन पदों में इस विषय के बारे में अधिक जानकारी प्राप्त कर सकते हैं: Why Navigation Properties are virtual by default in EF और Entity Framework 4.1 Virtual Properties

अन्य मॉडल जो मैं आपके मॉडल में प्रस्तावित करता हूं वह स्किल्स प्रॉपर्टी में आईसीओलेक्शन <> टाइप करें <> टाइप करें। जैसा कि आप इस post में देख सकते हैं, इस मामले में एक इंटरफ़ेस अच्छा अभ्यास है। यह आपको बाद में उस क्रियान्वयन को निर्दिष्ट करने देता है जो आप चाहते हैं (एक सूची <> हो सकती है)।

अब, अपनी समस्या पर वापस, अपने संदर्भ वर्ग में आपको ऑन-मॉडेल क्रिएटिंग विधि को ओवरराइड करने की आवश्यकता है ताकि बेसकार्ड तालिका में आईडी के लिए रिश्ते और कोई स्वत: उत्पन्न कॉलम निर्दिष्ट न हो।

public class YourContext : DbContext 
{ 
    public DbSet<BaseCard> BaseCards { get; set; } 

    public DbSet<Skill> Skill { get; set; } 

    //... 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     // Configure the primary key for BaseCard 
     modelBuilder.Entity<BaseCard>().HasKey(t => t.Id); 
     //specify no autogenerate the Id Column 
     modelBuilder.Entity<BaseCard>().Property(b => b.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

     //one-to-many relationship 
     modelBuilder.Entity<Skill>().HasRequired(c => c.BaseCard) 
       .WithMany(s => s.Skills) 
       .HasForeignKey(c => c.BaseCardId); 
    } 
} 

इस कॉन्फ़िगरेशन के साथ, आपको हमेशा एक अलग मूल्य के साथ बेसकार्ड ऑब्जेक्ट्स का आईडी सेट करना होगा।

आप उपयोग डेटा एनोटेशन चाहें, तो यह संभव है इस तरह से एक ही निर्दिष्ट करें:

public class BaseCard 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)] 
    public int Id { get; set; } 
    public virtual ICollection<Skill> Skills { get; set; } 
} 

public class Skill 
{ 
    [Key] 
    public int Id { get; set; } 

    public int BaseCardId { get; set; } 

    [ForeignKey("BaseCardId")] 
    public virtual BaseCard BaseCard { get; set; } 
} 

मेरे खुलने और सुविज्ञ एपीआई का उपयोग है, यह अधिक सुविधाजनक है और आप अपने मॉडल वर्गों को छूने के लिए नहीं है। आप इस post

+0

विस्तृत स्पष्टीकरण के लिए बहुत बहुत धन्यवाद, और मुझे 1 विकल्प देने के लिए बहुत कुछ। मैं कुछ और शोध करने जा रहा हूं और देख रहा हूं कि मैं किसका उपयोग कर रहा हूं। एक बार फिर धन्यवाद। – Rob

+0

octavioccl, जब मैं फ्लुएंट एपीआई का उपयोग करता हूं, तो मुझे अद्यतन-डेटाबेस -verbose को कॉल करते समय त्रुटि मिलती है। यह माइग्रेशन से बीज विधि को कॉल करता है। यहां मैं डेटाबेस भरने की कोशिश करता हूं लेकिन संदर्भ में बेसकार्ड को सहेजते समय मुझे निम्न त्रुटि मिलती है: IDENTITY_INSERT को बंद होने पर तालिका 'बेसकार्ड' में पहचान कॉलम के लिए स्पष्ट मान सम्मिलित नहीं किया जा सकता है। क्या ऐसा इसलिए है क्योंकि डीबी में माइग्रेट करते समय OnModelCreating विधि को कॉल नहीं किया जाता है? आप कैसे सुझाव देते हैं कि मैं डेटाबेस भर सकता हूं? – Rob

+0

क्या आपने पुराना डेटाबेस हटाया और एक नया निर्माण किया? मुझे लगता है कि ऐसा इसलिए है क्योंकि आपके पास बेसकार्ड के कॉलम आईडी के साथ पहचान के रूप में पुराना डेटाबेस है। – octavioccl

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