खोज…


परिचय

विषय चर्चा करता है कि आप एंटिटी फ्रेमवर्क कोड फर्स्ट का उपयोग करके एक-से-एक और कई-से-कई संबंधों को कैसे मैप कर सकते हैं।

एक-से-कई का मानचित्रण

तो चलिए आपको बताते हैं दो अलग-अलग इकाइयाँ, कुछ इस तरह:

public class Person
{
   public int PersonId { get; set; }
   public string Name { get; set; }
}

public class Car
{
   public int CarId { get; set; }
   public string LicensePlate { get; set; }
}

public class MyDemoContext : DbContext
{
   public DbSet<Person> People { get; set; }
   public DbSet<Car> Cars { get; set; }
}

और आप उन दोनों के बीच एक-से-कई संबंध स्थापित करना चाहते हैं, अर्थात्, एक व्यक्ति के पास शून्य, एक या अधिक कारें हो सकती हैं, और एक कार बिल्कुल एक व्यक्ति से संबंधित है। हर रिश्ता द्विदिश होता है, इसलिए अगर किसी व्यक्ति के पास कार है, तो कार उस व्यक्ति की है।

ऐसा करने के लिए बस अपने मॉडल वर्गों को संशोधित करें:

public class Person
{
   public int PersonId { get; set; }
   public string Name { get; set; }
   public virtual ICollection<Car> Cars { get; set; } // don't forget to initialize (use HashSet)
}

public class Car
{
   public int CarId { get; set; }
   public string LicensePlate { get; set; }
   public int PersonId { get; set; }
   public virtual Person Person { get; set; }
}

और यह बात है :) आप पहले से ही अपने संबंध स्थापित कर चुके हैं। डेटाबेस में, यह निश्चित रूप से विदेशी कुंजी के साथ दर्शाया गया है।

एक-से-कई मैपिंग: सम्मेलन के खिलाफ

अंतिम उदाहरण में, आप देख सकते हैं कि ईएफ यह पता लगाता है कि कौन सा कॉलम विदेशी कुंजी है और इसे किस ओर इशारा करना चाहिए। कैसे? सम्मेलनों का उपयोग करके। प्रकार के Person की एक संपत्ति होने के नाते, जिसे एक Person PersonId संपत्ति के साथ नामित किया जाता है, EF को यह निष्कर्ष निकालता है कि PersonId एक विदेशी कुंजी है, और यह प्रकार के Person द्वारा प्रस्तुत तालिका की प्राथमिक कुंजी को इंगित करता है।

लेकिन क्या आप कार प्रकार में मालिक को OwnerId और व्यक्ति को PersonId बदलने के लिए थे तो क्या होगा?

public class Car
{
   public int CarId { get; set; }
   public string LicensePlate { get; set; }
   public int OwnerId { get; set; }
   public virtual Person Owner { get; set; }
}

खैर, दुर्भाग्य से इस मामले में, कन्वेंशन सही DB स्कीमा का उत्पादन करने के लिए पर्याप्त नहीं हैं:

कोई चिंता नहीं; आप मॉडल में अपने रिश्तों और चाबियों के बारे में कुछ संकेतों के साथ ईएफ की मदद कर सकते हैं। OwnerId रूप में OwnerId संपत्ति का उपयोग करने के लिए बस अपनी Car प्रकार को कॉन्फ़िगर करें। एक इकाई प्रकार कॉन्फ़िगरेशन बनाएं और इसे अपने OnModelCreating() में लागू करें:

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
  public CarEntityTypeConfiguration()
  {
     this.HasRequired(c => c.Owner).WithMany(p => p.Cars).HasForeignKey(c => c.OwnerId);
  }
}

यह मूल रूप से कहता है कि Car पास एक आवश्यक संपत्ति है, Owner ( हैसरप्राइस्ड () ) और Owner के प्रकार में, Cars संपत्ति का उपयोग कार संस्थाओं ( WithMany () ) को वापस संदर्भित करने के लिए किया जाता है। और अंत में विदेशी कुंजी का प्रतिनिधित्व करने वाली संपत्ति निर्दिष्ट की जाती है ( HasForeignKey () )। यह हमें वह स्कीमा देता है जो हम चाहते हैं:

आप Person ओर से भी इस संबंध को कॉन्फ़िगर कर सकते हैं:

public class PersonEntityTypeConfiguration : EntityTypeConfiguration<Person>
{
  public PersonEntityTypeConfiguration()
  {
    this.HasMany(p => p.Cars).WithRequired(c => c.Owner).HasForeignKey(c => c.OwnerId);
  }
}

विचार समान है, बस पक्ष अलग हैं (ध्यान दें कि आप पूरी बात कैसे पढ़ सकते हैं: 'इस व्यक्ति के पास कई कारें हैं, प्रत्येक कार एक आवश्यक स्वामी के पास है')। इससे कोई फर्क नहीं पड़ता कि आप Person पक्ष या Car पक्ष से संबंध कॉन्फ़िगर करते हैं। आप दोनों को शामिल कर सकते हैं, लेकिन इस मामले में दोनों पक्षों पर समान संबंध निर्दिष्ट करने के लिए सावधान रहें!

मानचित्रण शून्य या एक-से-कई

पिछले उदाहरणों में एक कार एक व्यक्ति के बिना मौजूद नहीं हो सकती। क्या होगा यदि आप चाहते थे कि व्यक्ति कार की तरफ से वैकल्पिक हो? खैर, यह एक तरह से आसान है, यह जानना बहुत आसान है कि एक-से-कई कैसे करें। बस Car में PersonId को बदलने के लिए PersonId होना:

public class Car
{
    public int CarId { get; set; }
    public string LicensePlate { get; set; }
    public int? PersonId { get; set; }
    public virtual Person Person { get; set; }
}

और उसके बाद HasOptional () (या WithOptional ) का उपयोग करें, जिसके आधार पर आप कॉन्फ़िगरेशन करते हैं:

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
  public CarEntityTypeConfiguration()
  {
     this.HasOptional(c => c.Owner).WithMany(p => p.Cars).HasForeignKey(c => c.OwnerId);
  }
}

कई कई

आइए दूसरे परिदृश्य पर चलते हैं, जहां हर व्यक्ति के पास कई कारें हो सकती हैं और हर कार में कई मालिक हो सकते हैं (लेकिन फिर से, रिश्ते अप्रत्यक्ष हैं)। यह कई-से-कई संबंध हैं। सबसे आसान तरीका यह है कि कान्वेंट का उपयोग करके ईएफ को जादू करना चाहिए।

बस मॉडल को इस तरह बदलें:

 public class Person
{
   public int PersonId { get; set; }
   public string Name { get; set; }
   public virtual ICollection<Car> Cars { get; set; }
}

public class Car
{
   public int CarId { get; set; }
   public string LicensePlate { get; set; }        
   public virtual ICollection<Person> Owners { get; set; }
}

और स्कीमा:

लगभग आदर्श। जैसा कि आप देख सकते हैं, ईएफ ने एक जॉइन टेबल की आवश्यकता को पहचाना, जहां आप व्यक्ति-कार युग्मों का ट्रैक रख सकते हैं।

कई-कई: ज्वाइन टेबल को कस्टमाइज़ करना

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

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
   public CarEntityTypeConfiguration()
   {
      this.HasMany(c => c.Owners).WithMany(p => p.Cars)
          .Map(m =>
              {
                 m.MapLeftKey("OwnerId");
                 m.MapRightKey("CarId");
                 m.ToTable("PersonCars");
              }
        );
  }
}

यहां तक कि पढ़ने में आसान: इस कार में कई मालिक हैं ( HasMany () ), प्रत्येक मालिक के पास कई कारें ( WithMany () ) हैं। इसे मैप करें ताकि आप बाईं कुंजी को OwnerId ( MapLeftKey () ), दाईं ओर CarId ( MapRightKey () ) और संपूर्ण चीज़ टेबल पर्सनकार्स ( ToTable () ) पर मैप करें । और यह आपको बिल्कुल स्कीमा देता है:

कई-से-कई: कस्टम जॉइन इकाई

मुझे स्वीकार करना होगा, मैं वास्तव में ईएफ को ज्वाइन टेबल को हटाकर ज्वाइन यूनिट के साथ जुड़ने देने का प्रशंसक नहीं हूं। आप किसी व्यक्ति-कार एसोसिएशन को अतिरिक्त जानकारी ट्रैक नहीं कर सकते हैं (मान लें कि वह दिनांक जहाँ से यह मान्य है), क्योंकि आप तालिका को संशोधित नहीं कर सकते हैं।

इसके अलावा, ज्वाइन टेबल में CarId प्राथमिक कुंजी का हिस्सा है, इसलिए यदि परिवार एक नई कार खरीदता है, तो आपको पहले पुराने संघों को हटाना होगा और नए को जोड़ना होगा। EF इसे आपसे छुपाता है, लेकिन इसका मतलब है कि आपको इन दोनों ऑपरेशनों को एक साधारण अपडेट के बजाय करना होगा (इस बात का उल्लेख नहीं करने के लिए कि लगातार आवेषण / हटाए जाने से सूचकांक विखंडन हो सकता है - अच्छी बात यह है कि इसके लिए एक आसान निर्धारण है)।

इस मामले में आप क्या कर सकते हैं एक जॉइन्ट इकाई बना सकते हैं जिसमें एक विशिष्ट कार और एक विशिष्ट व्यक्ति दोनों का संदर्भ हो। मूल रूप से आप अपने कई-से-कई संघों को दो एक-से-कई संघों के संयोजन के रूप में देखते हैं:

public class PersonToCar
{
   public int PersonToCarId { get; set; }
   public int CarId { get; set; }
   public virtual Car Car { get; set; }
   public int PersonId { get; set; }
   public virtual Person Person { get; set; }
   public DateTime ValidFrom { get; set; }
}

public class Person
{
  public int PersonId { get; set; }
  public string Name { get; set; }
  public virtual ICollection<PersonToCar> CarOwnerShips { get; set; }
}

public class Car
{
  public int CarId { get; set; }
  public string LicensePlate { get; set; }        
  public virtual ICollection<PersonToCar> Ownerships { get; set; }
}

public class MyDemoContext : DbContext
{
  public DbSet<Person> People { get; set; }
  public DbSet<Car> Cars { get; set; }
  public DbSet<PersonToCar> PersonToCars { get; set; }
}

यह मुझे बहुत अधिक नियंत्रण देता है और यह बहुत अधिक लचीला है। मैं अब एसोसिएशन में कस्टम डेटा जोड़ सकता हूं और प्रत्येक एसोसिएशन की अपनी प्राथमिक कुंजी है, इसलिए मैं कार या मालिक के संदर्भ को अपडेट कर सकता हूं।

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



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow