EF Core 3.1.7 तालिका में कई 1: 1 रिश्तों के लिए डेटा एनोटेशन

Aug 17 2020

मुझे डेटा एनोटेशन के लिए एक से अधिक 1: 1 रिलेशनशिप को मैप करने में समस्या आ रही है ताकि EF Core 3.11.7 इसे समझ सके और माइग्रेशन का निर्माण कर सके।

मेरे पास एक व्यक्ति तालिका और नोट्स तालिका है। व्यक्ति में 0: M नोट्स संबंध है। एक व्यक्ति के रिकॉर्ड में 0 या अधिक नोट हो सकते हैं।

नोट्स तालिका में एक CreatedBy फ़ील्ड है जो एक व्यक्ति है। इसमें एक LastEditedBy फ़ील्ड भी है जो एक व्यक्ति भी है। EF Note.CreatedBy के लिए संबंध बनाने के तरीके पर बमबारी करता रहता है। यदि यह गैर ईएफ होता, तो दोनों क्षेत्र उचित व्यक्ति रिकॉर्ड के पर्सिड के साथ सम्मिलित होते। यह कैसे करते हैं, डेटा एनोटेशन के साथ अधिमानतः, ईएफ कोर को समझाएं?

जब मैं एक माइग्रेशन बनाने का प्रयास करता हूं तो वह विफल हो जाता है और कहता है: System.InvalidOperationException: नेविगेशन प्रॉपर्टी 'नोट.क्रिएटेडबाय' टाइप 'पर्सन' द्वारा दर्शाए गए संबंध को निर्धारित करने में असमर्थ। या तो संबंध को मैन्युअल रूप से कॉन्फ़िगर करें, या '' NotMapped] विशेषता का उपयोग करके या 'OnModelCreating' में EntityTypeBuilder.Ignore का उपयोग करके इस संपत्ति को अनदेखा करें।

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Linq;
    using System.Threading.Tasks;

namespace VetReg.Domain.Model
{
    public class Family
    {
        public int FamilyID { get; set; } = -1;
        public string FamilyName { get; set; }
        public List<Pet> Pets { get; set; } = new List<Pet>();
        public List<PersonFamily> People { get; set; }
        public int AddressID { get; set; } = -1;
        public List<Note> Notes { get; set; }
    }

    public class Person
    {
        public int PersonID { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public DateTime? Birthdate { get; set; }
        public string Password { get; set; }
        public List<PersonFamily> Families { get; set; }
        public List<Note> Notes { get; set; }
    } // class People

    public class Note
    {
        public int NoteID { get; set; }

        public int CreatedByID { get; set; }

        [ForeignKey("CreatedByID")]
        public Person CreatedBy { get; set; }
        public DateTime DateCreated { get; set; }

        public int LastEditByID { get; set; }

        [ForeignKey("LastEditByID")]
        public Person LastEditBy { get; set; }
        public DateTime? LastEditDate { get; set; }
        public string NoteText { get; set; }
    }

    public class PersonFamily
    {
        public int PersonID { get; set; }
        public int FamilyID { get; set; }
        public Person Person { get; set; }
        public Family Family { get; set; }
    }

}

जवाब

IvanStoev Aug 17 2020 at 15:11

सवाल यह है (और यह वही है जो ईएफ को रिश्तों को निर्धारित करने के लिए असंभव बनाता है) Person.Notesऔर Note.CreatedBy/ Note.LastEditBy- के बीच क्या संबंध है ? आपने कहा है कि 0: M संबंध Personऔर के बीच है Note, लेकिन ध्यान दें कि संभावित रूप से 3 एक-से-कई संबंध हैं - व्यक्ति के साथ जुड़े नोट्स, व्यक्ति द्वारा बनाए गए नोट्स और व्यक्ति द्वारा संपादित नोट, जो संभावित रूप से 3 FKs की ओर जाता है नोट में व्यक्ति।

यह भी ध्यान दें कि किसी भी नेविगेशन गुण की आवश्यकता नहीं है, लेकिन वर्तमान में उन्हें जोड़ा जाना चाहिए।

मान लें कि आप 3 रिश्ते चाहते हैं, अर्थात् Note.CreatedBy/ Note.LastEditByऔर के बीच कोई संबंध नहीं है Person.Notes, तो आपको ईएफ को बताने की आवश्यकता है Note.CreatedByऔर Note.LastEditByइसमें (उर्फ उलटा) नेविगेशन संपत्ति नहीं है Person। डेटा एनोटेशन के साथ यह संभव नहीं है। उस उद्देश्य के लिए केवल उपलब्ध डेटा एनोटेशन [InverseProperty(...)]रिक्त / अशक्त स्ट्रिंग नाम को स्वीकार नहीं करता है, इसलिए इसका उपयोग यहां आवश्यक नहीं है।

साथ ही यहाँ एक और समस्या है जिसका सामना आप करंट को हल करने के बाद करेंगे, जिसे डेटा एनोटेशन से भी हल नहीं किया जा सकता है। के बाद से आप एक से अधिक आवश्यक है से रिश्तों (इस प्रकार डिफ़ॉल्ट रूप से हटाने के झरना) Personके लिए Note, यह प्रसिद्ध "चक्र या एक से अधिक झरना पथ" SqlServer साथ समस्या पैदा करता है, और झरना हटाना कम से कम एक को बंद करने की आवश्यकता है।

कहा जा रहा है कि, प्रश्न में मॉडल निम्नलिखित न्यूनतम धाराप्रवाह विन्यास की जरूरत है:

modelBuilder.Entity<Note>()
    .HasOne(e => e.CreatedBy)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Note>()
    .HasOne(e => e.LastEditBy)
    .WithMany()
    .OnDelete(DeleteBehavior.Restrict);

मूल मुद्दे के लिए आवश्यक HasOne/ WithManyजोड़े हैं। एक बार जब आप ऐसा करते हैं, तो ईएफ कोर स्वचालित रूप Person.Notesसे बिना किसी उल्टे नेविगेशन संपत्ति और छाया एफपी संपत्ति (और कॉलम) के साथ तीसरे वैकल्पिक संबंध को मैप करेगा, जिसे "पर्सनल" कहा जाता है, अर्थात

modelBuilder.Entity<Person>()
    .HasMany(e => e.Notes)
    .WithOne()
    .HasForeignKey("PersonId");

कई कैस्केड पथों के साथ दूसरे मुद्दे के संबंध में, Restrictआप के बजाय किसी भी गैर कैस्केडिंग विकल्प या नए का उपयोग कर सकते हैं ClientCascade। और यह केवल एक रिश्ते के लिए हो सकता है, जैसे ही यह "कैस्केड पथ" को तोड़ता है (जाहिर है कि आप चक्र को नहीं तोड़ सकते क्योंकि यह मॉडल द्वारा मांग की गई है)।