8

मैं एक एसएसएल सर्वर 2012 एक्सप्रेस डीबी द्वारा समर्थित एंटिटी-फ्रेमवर्क कोर (संस्करण "EntityFramework.Core": "7.0.0-rc1-final") के साथ एएसपी.नेट एमवीसी 6 प्रोजेक्ट पर काम कर रहा हूं।एंटिटी फ्रेमवर्क कोर कोड-फर्स्ट: कैस्केड कई से कई रिश्तों को हटाता है

मुझे Person इकाई और Address इकाई के बीच कई से अधिक रिश्तों को मॉडल करने की आवश्यकता है। this गाइड के अनुसार मैंने इसे PersonAddress जॉइन-टेबल इकाई के साथ मॉडल किया, क्योंकि इस तरह से मैं कुछ अतिरिक्त जानकारी स्टोर कर सकता हूं।

  • एक Person उदाहरण नष्ट कर दिया जाता है, तो सभी संबंधित PersonAddress उदाहरणों से हटाना होगा:

    मेरे लक्ष्य सेट अप करने के लिए अपने सिस्टम इस तरह से है। सभी Address उदाहरण जिन्हें वे संदर्भित करते हैं उन्हें भी हटाया जाना चाहिए, केवल तभी यदि वे अन्य PersonAddress उदाहरणों से संबंधित नहीं हैं।

  • यदि PersonAddress उदाहरण हटा दिया गया है, तो Address उदाहरण यह केवल तब से हटाया जाना चाहिए जब यह अन्य PersonAddress उदाहरणों से संबंधित नहीं है। सभी Person उदाहरण जीना चाहिए।
  • यदि Address उदाहरण हटा दिया गया है, तो सभी संबंधित PersonAddress उदाहरण हटा दिए जाने चाहिए। सभी Person उदाहरण जीना चाहिए।

मुझे लगता है कि काम के सबसे Person और Address के बीच कई-से-अनेक संबंध में किया जाना चाहिए, लेकिन मैं कुछ तर्क भी लिखने के लिए उम्मीद है। मैं इस सवाल से इस हिस्से को छोड़ दूंगा। मुझे इसमें दिलचस्पी है कि मेरे कई से अधिक रिश्तों को कैसे कॉन्फ़िगर किया जाए।

वर्तमान स्थिति है।

यह Person इकाई है। कृपया ध्यान दें कि इस इकाई को अन्य माध्यमिक संस्थाओं के साथ एक से कई रिश्ते मिल गए हैं।

public class Person 
{ 
    public int Id {get; set; } //PK 
    public virtual ICollection<Telephone> Telephones { get; set; } //navigation property 
    public virtual ICollection<PersonAddress> Addresses { get; set; } //navigation property for the many-to-many relationship 
} 

यह Address इकाई है।

public class Address 
{ 
    public int Id { get; set; } //PK 
    public int CityId { get; set; } //FK 
    public City City { get; set; } //navigation property 
    public virtual ICollection<PersonAddress> People { get; set; } //navigation property 
} 

यह PersonAddress इकाई है।

public class PersonAddress 
{ 
    //PK: PersonId + AddressId 
    public int PersonId { get; set; } //FK 
    public Person Person {get; set; } //navigation property 
    public int AddressId { get; set; } //FK 
    public Address Address {get; set; } //navigation property 
    //other info removed for simplicity 
} 

यह DatabaseContext इकाई है, जहां सभी रिश्तों में वर्णित किया जाता है।

public class DataBaseContext : DbContext 
{ 
    public DbSet<Person> People { get; set; } 
    public DbSet<Address> Addresses { get; set; } 

    protected override void OnModelCreating(ModelBuilder builder) 
    {    
     //All the telephones must be deleteded alongside a Person. 
     //Deleting a telephone must not delete the person it refers to. 
     builder.Entity<Person>() 
      .HasMany(p => p.Telephones) 
      .WithOne(p => p.Person); 

     //I don't want to delete the City when I delete an Address 
     builder.Entity<Address>() 
      .HasOne(p => p.City) 
      .WithMany(p => p.Addresses) 
      .IsRequired().OnDelete(Microsoft.Data.Entity.Metadata.DeleteBehavior.Restrict); 

     //PK for the join entity 
     builder.Entity<PersonAddress>() 
      .HasKey(x => new { x.AddressId, x.PersonId }); 

     builder.Entity<PersonAddress>() 
      .HasOne(p => p.Person) 
      .WithMany(p => p.Addresses) 
      .IsRequired(); 

     builder.Entity<PersonAddress>() 
      .HasOne(p => p.Address) 
      .WithMany(p => p.People) 
      .IsRequired(); 
    } 
} 

दोनों Telephone और City संस्थाओं सरलता के लिए हटा दिया गया है।

यह Person को हटाने के लिए कोड है।

Person person = await _context.People.SingleAsync(m => m.Id == id); 
try 
{ 
    _context.People.Remove(person); 
    await _context.SaveChangesAsync(); 
} 
catch (Exception ex) 
{ 

} 

मेरी रीडिंग .Include() परहेज डीबी अंतिम CASCADE हटाता की देखभाल करने देगा का सवाल है। मुझे खेद है, लेकिन मुझे एसओ सवाल याद नहीं है जहां इस अवधारणा को स्पष्ट किया गया था।

यदि मैं इस कोड को चलाता हूं तो मैं this workaround का उपयोग कर डीबी बीज कर सकता हूं।मैं परीक्षण-को हटाने से ऊपर कोड के साथ एक Person इकाई चाहते हैं, तो मैं इस अपवाद:

The DELETE statement conflicted with the REFERENCE constraint "FK_PersonAddress_Person_PersonId". The conflict occurred in database "<dbName>", table "<dbo>.PersonAddress", column 'PersonId'. 
The statement has been terminated. 

मैं किसी भी भाग्य के बिना DatabaseContext.OnModelCreating विधि में कई रिश्ते व्यवस्था का परीक्षण किया।

अंत में, यहां मेरा प्रश्न है। लक्ष्य के मुताबिक Person और मेरे आवेदन से संबंधित इकाइयों को सही तरीके से हटाने के लिए मुझे अपने कई से अधिक रिश्तों को कैसे कॉन्फ़िगर करना चाहिए?

सभी को धन्यवाद।

उत्तर

0

सबसे पहले मैं तुम्हें DeleteBehavior.Restrict साथ शहर और पता संबंध स्थापित किया है देख सकते हैं और आप कहते हैं: '// मैं शहर जब मैं कोई पता हटाना नष्ट करने के लिए नहीं करना चाहते हैं'।
लेकिन आपको यहां प्रतिबंधित करने की आवश्यकता नहीं है, क्योंकि DeleteBehavior.Cascade शहर भी हटाया नहीं जाएगा। आप इसे गलत पक्ष से देख रहे हैं। क्या Cascade यहां होता है जब कोई शहर हटा दिया जाता है तो उससे संबंधित सभी पते भी हटा दिए जाते हैं। और वह व्यवहार तार्किक है।

दूसरा, आपके कई से अधिक रिश्ते ठीक हैं। व्यक्ति को हटाते समय व्यक्ति एड्रेस टेबल से अपने लिंक कैस्केड के कारण स्वचालित रूप से हटा दिए जाएंगे। और यदि आप केवल उस व्यक्ति से जुड़े पते को हटाना चाहते हैं तो आपको इसे मैन्युअल रूप से करना होगा। व्यक्ति को हटाने के लिए आपको वास्तव में उन पते को हटाना होगा, यह जानने के लिए कि क्या हटाना है।
तो तर्क निम्नलिखित होना चाहिए:
1. व्यक्ति के सभी रिकॉर्ड के माध्यम से पूछें जहां PersonId = person.Id;
2. उनमें से केवल उन लोगों को लेते हैं जिनके पास PersonAddress तालिका में AddressId का एकल अवसर होता है, और उन्हें व्यक्तिगत तालिका से हटा दिया जाता है।
3. अब व्यक्ति को हटाएं।

आप सीधे कोड में ऐसा कर सकता है, या यदि आप डेटाबेस यह तुम्हारे लिए क्या करना चाहते हैं, ट्रिगर समारोह के साथ चरण 2 के लिए बनाया जा सकता है: जब PersonAddress से पंक्ति के बारे में हटाए जाने के लिए जांच है अगर वहाँ कोई और अधिक कर रहे हैं उसी व्यक्ति के साथ पंक्तियां उस व्यक्ति में एड्रेस तालिका जिस स्थिति में इसे पता तालिका से हटा दें।

अधिक यहाँ जानकारी:
How to cascade delete over many to many table
How do I delete from multiple tables using INNER JOIN in SQL server

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