खोज…


परिचय

यह विषय चर्चा करता है कि एंटिटी फ्रेमवर्क का उपयोग करके एक-से-एक प्रकार के रिश्तों को कैसे मैप किया जाए।

एक-शून्य या एक को मैप करना

तो चलिए फिर कहते हैं कि आपके पास निम्नलिखित मॉडल हैं:

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 int CarId { get; set; }
  public virtual Car Car { get; set; }
}

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

और विन्यास:

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
  public CarEntityTypeConfiguration()
  {
     this.HasRequired(c => c.Person).WithOptional(p => p.Car);                        
  }
}    

इस समय तक यह स्व-व्याख्यात्मक होना चाहिए। कार में एक आवश्यक व्यक्ति ( HasRequired () ) है, जिसके पास एक वैकल्पिक कार ( WithOptional () ) है। फिर, इससे कोई फर्क नहीं पड़ता कि आप इस रिश्ते को किस ओर से कॉन्फ़िगर करते हैं, बस सावधान रहें जब आप हस / विथ और आवश्यक / वैकल्पिक के सही संयोजन का उपयोग करें। Person ओर से, यह इस तरह दिखेगा:

public class PersonEntityTypeConfiguration : EntityTypeConfiguration<Person>
{
  public PersonEntityTypeConfiguration()
  {
     this.HasOptional(p => p.Car).WithOptional(c => c.Person);                        
  }
}    

अब db स्कीमा देखें:

बारीकी से देखें: आप देख सकते हैं कि Car को संदर्भित करने के लिए People में कोई FK नहीं है। इसके अलावा, Car में FK PersonId नहीं है, लेकिन CarId । यहाँ FK के लिए वास्तविक स्क्रिप्ट है:

ALTER TABLE [dbo].[Cars]  WITH CHECK ADD  CONSTRAINT [FK_dbo.Cars_dbo.People_CarId] FOREIGN KEY([CarId])
REFERENCES [dbo].[People] ([PersonId])

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

विचार यह है कि प्रत्येक व्यक्ति के पास एक कार हो सकती है, और वह कार केवल उस व्यक्ति की हो सकती है। या ऐसे व्यक्ति रिकॉर्ड हो सकते हैं, जिनके पास कारें नहीं हैं।

तो यह विदेशी कुंजी के साथ कैसे प्रतिनिधित्व किया जा सकता है? जाहिर है, वहाँ एक हो सकता है PersonId में Car , और एक CarId में People । लागू करने के लिए हर व्यक्ति को केवल एक कार हो सकता है, PersonId में अद्वितीय होना करने के लिए होता Car । लेकिन अगर PersonId में अद्वितीय है People , तो कैसे आप दो या अधिक रिकॉर्ड जोड़ सकते हैं जहां PersonId है NULL (एक से अधिक कार मालिकों की जरूरत नहीं है कि)? उत्तर: आप नहीं कर सकते हैं (वास्तव में, आप SQL Server 2008 और नए में एक फ़िल्टर किया गया अनन्य अनुक्रमणिका बना सकते हैं, लेकिन एक पल के लिए इस तकनीकीता के बारे में भूल जाते हैं; अन्य RDBMS का उल्लेख नहीं करना)। उस मामले का उल्लेख नहीं करने के लिए जहां आप रिश्ते के दोनों सिरों को निर्दिष्ट करते हैं ...

इस नियम को लागू करने का एकमात्र वास्तविक तरीका है यदि People और Car तालिकाओं में 'समान' प्राथमिक कुंजी (कनेक्टेड रिकॉर्ड में समान मान) हो। और ऐसा करने के लिए, CarId in Car में एक PK और एक FK दोनों लोगों का PK होना चाहिए। और यह पूरे स्कीमा को गड़बड़ कर देता है। जब मैं इसका उपयोग करता हूं तो मैं Car PersonId में PK / FK का नाम देता PersonId , और तदनुसार इसे कॉन्फ़िगर करता PersonId :

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

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

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
  public CarEntityTypeConfiguration()
  {
     this.HasRequired(c => c.Person).WithOptional(p => p.Car);
     this.HasKey(c => c.PersonId);
  }
}

आदर्श नहीं है, लेकिन शायद थोड़ा बेहतर है। फिर भी, आपको इस समाधान का उपयोग करते समय सतर्क रहना होगा, क्योंकि यह सामान्य नामकरण सम्मेलनों के खिलाफ जाता है, जो आपको भटका सकता है। इस मॉडल से उत्पन्न स्कीमा इस प्रकार है:

इसलिए यह संबंध डेटाबेस स्कीमा द्वारा नहीं बल्कि एंटिटी फ्रेमवर्क द्वारा ही लागू किया जाता है। इसीलिए जब आप इसे इस्तेमाल करते हैं तो आपको बहुत सावधान रहना होगा, न कि किसी को सीधे डेटाबेस से गुस्सा करने देना।

एक-एक को मैप करना

एक-से-एक को मैप करना (जब दोनों पक्षों की आवश्यकता होती है) भी एक मुश्किल काम है।

आइए कल्पना करें कि इसे विदेशी कुंजी के साथ कैसे दर्शाया जा सकता है। फिर, एक CarId में People को संदर्भित करता है CarId में Car , और एक PersonId कार में है कि को संदर्भित करता है PersonId में People

अब अगर आप कार रिकॉर्ड डालना चाहते हैं तो क्या होगा? इसे सफल होने के लिए, इस कार रिकॉर्ड में निर्दिष्ट एक PersonId होना चाहिए, क्योंकि यह आवश्यक है। और इस PersonId के वैध होने के लिए, People में संबंधित रिकॉर्ड मौजूद होना चाहिए। ठीक है, तो चलिए आगे बढ़ते हैं और उस व्यक्ति के रिकॉर्ड को सम्मिलित करते हैं। लेकिन यह सफल होने के लिए, एक वैध CarId व्यक्ति रिकॉर्ड में होना चाहिए - लेकिन वह कार अभी तक सम्मिलित नहीं की गई है! यह नहीं हो सकता है, क्योंकि हमें पहले संदर्भित व्यक्ति को रिकॉर्ड करना होगा। लेकिन हम संदर्भित व्यक्ति रिकॉर्ड को सम्मिलित नहीं कर सकते, क्योंकि यह वापस कार रिकॉर्ड को संदर्भित करता है, इसलिए इसे पहले डाला जाना चाहिए (विदेशी की-सीमेंट :))।

इसलिए इसे 'तार्किक' तरीके से प्रस्तुत नहीं किया जा सकता है। फिर, आपको एक विदेशी कुंजी को छोड़ना होगा। आप जिसे गिराते हैं वह आप पर निर्भर है। जिस पक्ष को एक विदेशी कुंजी के साथ छोड़ दिया जाता है, उसे 'आश्रित' कहा जाता है, वह पक्ष जिसे बिना विदेशी कुंजी के छोड़ दिया जाता है उसे 'प्रमुख' कहा जाता है। और फिर, आश्रित में विशिष्टता सुनिश्चित करने के लिए, पीके को एफके होना चाहिए, इसलिए एफके कॉलम को जोड़ना और आयात करना कि आपके मॉडल का समर्थन नहीं किया गया है।

तो यहाँ विन्यास है:

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
  public CarEntityTypeConfiguration()
  {
    this.HasRequired(c => c.Person).WithRequiredDependent(p => p.Car);
    this.HasKey(c => c.PersonId);
  }
}

अब तक आपको वास्तव में इसका तर्क प्राप्त करना चाहिए था :) बस याद रखें कि आप दूसरे पक्ष को भी चुन सकते हैं, बस WithRequired के निर्भर / प्रधान संस्करणों का उपयोग करने के लिए सावधान रहें (और आपको अभी भी पीके को कार में कॉन्फ़िगर करना होगा)।

public class PersonEntityTypeConfiguration : EntityTypeConfiguration<Person>
{
  public PersonEntityTypeConfiguration()
  {
    this.HasRequired(p => p.Car).WithRequiredPrincipal(c => c.Person);
  }
}

यदि आप DB स्कीमा की जाँच करते हैं, तो आप पाएंगे कि यह बिल्कुल वैसा ही है जैसा कि वन-टू-वन या जीरो समाधान के मामले में था। ऐसा इसलिए है क्योंकि फिर से, यह स्कीमा द्वारा लागू नहीं किया गया है, लेकिन ईएफ द्वारा ही। तो फिर, सावधान रहें :)

मैपिंग एक या शून्य से एक या शून्य

और खत्म करने के लिए, आइए संक्षेप में उस मामले को देखें जब दोनों पक्ष वैकल्पिक हों।

अब तक आपको इन उदाहरणों से वास्तव में ऊब जाना चाहिए :), इसलिए मैं विवरणों में नहीं जा रहा हूं और दो एफके-एस और संभावित समस्याओं के विचार के साथ खेलता हूं और आपको इन नियमों को लागू नहीं करने के खतरों के बारे में चेतावनी देता हूं। स्कीमा लेकिन केवल ईएफ में ही।

यहाँ विन्यास है जिसे आपको लागू करने की आवश्यकता है:

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
  public CarEntityTypeConfiguration()
  {
    this.HasOptional(c => c.Person).WithOptionalPrincipal(p => p.Car);
    this.HasKey(c => c.PersonId);
  }
}

फिर, आप दूसरी तरफ से भी कॉन्फ़िगर कर सकते हैं, बस सही तरीकों का उपयोग करने के लिए सावधान रहें :)



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