5

अस्पष्ट शीर्षक के लिए क्षमा करें, यह एक पंक्ति में इस बयान नहीं किया जा:विदेशी कुंजी को अपडेट करने के बाद असंगत बाधा क्यों असंगत हो जाती है?

मैं, 2 संस्थाओं User और UserAddress है जहां उपयोगकर्ता 2 विदेशी कुंजी DefaultInvoiceAddressId और DefaultDeliveryAddressId है और UserAddress एक UserId विदेशी कुंजी है।

उपयोगकर्ता ऑब्जेक्ट में डिफ़ॉल्ट पते (DefaultInvoiceAddress और DefaultDeliveryAddress) के साथ-साथ उनके सभी पते के लिए नेविगेशन गुण हैं: AllAddresses

मैपिंग आदि काम करता है, उपयोगकर्ताओं और पतों को बनाने और अद्यतन करने के लिए भी काम करता है।

हालांकि उपयोगकर्ता के मौजूदा पते को सेट करने के दौरान काम नहीं करता है उदा। DefaultInvoiceAddress। एसक्यूएल शब्दों में, मैं क्या करना चाहता हूं UPDATE USER SET DefaultInvoiceAddressId = 5 WHERE Id = 3 है।

मैं इस की कोशिश की है निम्नलिखित रास्ता:

private void MarkAs(User user, UserAddress address, User.AddressType type) { 
     if (context.Entry(user).State == EntityState.Detached) 
      context.Users.Attach(user); 

     // guess I don't really need this: 
     if (context.Entry(address).State == EntityState.Detached) 
      context.UserAddresses.Attach(address); 

     if (type.HasFlag(User.AddressType.DefaultInvoice)) { 
      user.DefaultInvoiceAddressId = address.Id; 
      user.DefaultInvoiceAddress = null; 
      context.Entry(user).Property(u => u.DefaultInvoiceAddressId).IsModified = true; 
     } 

     if (type.HasFlag(User.AddressType.DefaultDelivery)) { 
      user.DefaultDeliveryAddressId = address.Id; 
      user.DefaultDeliveryAddress = null; 
      context.Entry(user).Property(u => u.DefaultDeliveryAddressId).IsModified = true; 
     } 
    } 

इस विधि कहा जाता है दोनों के साथ-साथ नई UserAddresses बनाते समय जब पतों को अद्यतन करने के रूप में।

The changes to the database were committed successfully, 
but an error occurred while updating the object context. 
The ObjectContext might be in an inconsistent state. 
Inner exception message: A referential integrity constraint violation occurred: 
The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship. 

मैं एक उपयोगकर्ता वस्तु मैं डेटाबेस और DefaultDeliveryAddress इसमें से पुनर्प्राप्त, जो मैं के माध्यम से इसे के साथ लोड के साथ विधि कॉल: बनाने के परिदृश्य से काम करता है के रूप में उम्मीद, हालांकि अद्यतन मामले में मैं निम्न त्रुटि प्राप्त उत्सुक लोडिंग।

var user = mainDb.User.Get(UnitTestData.Users.Martin.Id, User.Include.DefaultAddresses); 
var existingAddress = user.DefaultDeliveryAddress; 
mainDb.User.Addresses.SetAs(user, existingAddress, User.AddressType.DefaultInvoice)) 
// the SetAs method verfies input parameters, calls MarkAs and then SaveChanges 

संक्षेप में, मैं बस भी अपने DefaultInvoiceAddress जो आसानी से ऊपर एसक्यूएल अद्यतन कमांड के साथ पूरा किया जाएगा यदि कोई उपयोगकर्ता की DefaultDeliveryAddress बनाना चाहते, लेकिन मैं अपने एफई कोड के साथ कुछ याद कर रहा हूँ। मैं पहले से ही देख लिया है कि:

  • केवल ईद सेट किया गया है, नेविगेशन संपत्ति (DefaultInvoiceAddress) शून्य पर
  • UserAddress.UserId = User.Id (जाहिर है, क्योंकि यह पहले से ही करने के लिए असाइन किया गया है फिर से सेट किया गया है उपयोगकर्ता)
  • उपयोगकर्ता वस्तु Modified हो जाएगा (के रूप में संशोधित
  • मैं भी दोनों डिफ़ॉल्ट पता नेविगेशन प्रॉपर्टी को साफ़ करने की कोशिश की, क्योंकि उसके गुण में से एक के रूप में चिह्नित किया जा रहा है डिबगर के साथ की जाँच), है, लेकिन है कि या तो
  • मदद नहीं की

मुझे संदेह है कि यह समस्या उपयोगकर्ता इकाई के कारण 2 उपयोगकर्ता संदर्भ के कारण है, और दोनों विदेशी कुंजी एक ही पते के संदर्भ में सेट हैं - मैं इसके साथ काम करने के लिए ईएफ कैसे प्राप्त कर सकता हूं?

अद्यतन:

यहाँ उपयोगकर्ता संस्था की मैपिंग कर रहे हैं:

// from UserMap.cs: 
... 
     Property(t => t.DefaultInvoiceAddressId).HasColumnName("DefaultInvoiceAddressId"); 
     Property(t => t.DefaultDeliveryAddressId).HasColumnName("DefaultDeliveryAddressId"); 

     // Relationships 
     HasOptional(t => t.DefaultInvoiceAddress) 
      .WithMany() 
      .HasForeignKey(t => t.DefaultInvoiceAddressId); 

     HasOptional(t => t.DefaultDeliveryAddress) 
      .WithMany() 
      .HasForeignKey(t => t.DefaultDeliveryAddressId); 

     HasMany(t => t.AllAddresses) 
      .WithRequired() 
      .HasForeignKey(t => t.UserId) 
      .WillCascadeOnDelete(); 

UserAddress उपयोगकर्ता के लिए वापस नहीं नेविगेशन गुण है; यह केवल contanis HasMaxLength और HasColumnName सेटिंग्स (मैं उन्हें कुछ हद तक पठनीय रखने के लिए बाहर रखता हूं)।

अद्यतन 2

यहाँ Intellitrace से निष्पादित आदेश दिया गया है:

The command text "update [TestSchema].[User] 
set [DefaultInvoiceAddressId] = @0 
where ([Id] = @1) 
" was executed on connection "Server=(localdb)\..." 

मेरे लिए ठीक लग रहा है; ऐसा लगता है कि केवल ईएफ राज्य प्रबंधक कुंजी मैपिंग द्वारा भ्रमित हो जाता है।

+0

उपयोगकर्ता और पता परिभाषाओं और विन्यास पोस्ट करें। उत्पादित वास्तविक SQL राज्यों को भी पोस्ट करें। –

+0

हम्म, चयन को केवल एक क्वेरी से प्राप्त किया जा सकता है लेकिन अद्यतन/INSERT के लिए आपको SQL एमजीएमटी स्टूडियो या प्रोफ़ाइल की आवश्यकता होगी (मिनी प्रोफाइलर एक लुक के लायक लगता है)। –

+0

मुझे इंटेलिट्रेस के साथ बयान प्राप्त करने का कोई तरीका मिला, मैंने आदेश के साथ अपना प्रश्न अपडेट कर दिया है। – enzi

उत्तर

7

समस्या का पता चला: स्पष्ट रूप से यह नेविगेशन गुणों को शून्य करने के लिए काफी अंतर बनाता है, क्योंकि ईएफ अन्यथा इसे एक इच्छित परिवर्तन/अद्यतन (कम से कम मुझे संदेह है) के रूप में समझ सकता है।

MarkAs विधि के निम्न संस्करण काम करता है:

private void MarkAs(User user, UserAddress address, User.AddressType type) { 
     if (context.Entry(user).State == EntityState.Detached) { 
      // clear navigation properties before attaching the entity 
      user.DefaultInvoiceAddress = null; 
      user.DefaultDeliveryAddress = null; 
      context.Users.Attach(user); 
     } 
     // address doesn't have to be attached 

     if (type.HasFlag(User.AddressType.DefaultInvoice)) { 
      // previously I tried to clear the navigation property here 
      user.DefaultInvoiceAddressId = address.Id; 
      context.Entry(user).Property(u => u.DefaultInvoiceAddressId).IsModified = true; 
     } 

     if (type.HasFlag(User.AddressType.DefaultDelivery)) { 
      user.DefaultDeliveryAddressId = address.Id; 
      context.Entry(user).Property(u => u.DefaultDeliveryAddressId).IsModified = true; 
     } 
    } 

भविष्य पाठकों के लिए मेरी निष्कर्ष सारांश में:

  • आप विदेशी कुंजी गुण के माध्यम से संस्थाओं को अद्यतन करना चाहते हैं, स्पष्ट नेविगेशन गुण। ईएफ को अपडेट स्टेटमेंट को समझने की आवश्यकता नहीं है।
  • से पहले स्पष्ट नेविगेशन गुणआप एक संदर्भ में एक इकाई संलग्न करते हैं, अन्यथा ईएफ एक बदलाव के रूप में व्याख्या कर सकता है (मेरे मामले में विदेशी कुंजी शून्य है, अगर ऐसा नहीं है तो ईएफ शायद अनदेखा करने के लिए पर्याप्त स्मार्ट हो सकता है नेविगेशन संपत्ति परिवर्तन)।

मैं अन्य (अधिक योग्य) पाठकों को जवाब देने का मौका देने के लिए तुरंत अपना जवाब स्वीकार नहीं करूंगा; अगर अगले 2 दिनों में कोई जवाब पोस्ट नहीं किया गया है, तो मैं इसे स्वीकार करूंगा।

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