2011-08-07 4 views
13

मुझे नीचे वर्णित परिदृश्य का समाधान खोजने में मुझे बहुत लंबा रास्ता लगा। प्रतीत होता है कि एक साधारण संबंध होना मुश्किल साबित हुआ। सवाल यह है:इकाई फ्रेमवर्क, कोड प्रथम, स्वतंत्र संघों के साथ "एक से कई" संबंध अपडेट करें

एंटीटी फ्रेमवर्क 4.1 (कोड फर्स्ट दृष्टिकोण) और "इंडिपेंडेंट एसोसिएशन" का उपयोग करके मैं "अलग" परिदृश्य में मौजूदा "कई से एक" रिश्ते को अलग-अलग अंत कैसे सौंपूं (मेरे में Asp.Net मामला)।

मॉडल:

मुझे लगता है कि स्वतंत्र संघों के बजाय ForeignKey संबंधों का उपयोग कर एक विकल्प हो गया होता, लेकिन यह मेरी प्राथमिकता मेरा Pocos में एक ForeignKey कार्यान्वयन नहीं किया गया था।

public class Customer:Person 
{ 
    public string Number { get; set; } 
    public string NameContactPerson { get; set; } 
    private ICollection<Target> _targets; 

    // Independent Association 
    public virtual ICollection<Target> Targets 
    { 
     get { return _targets ?? (_targets = new Collection<Target>()); } 
     set { _targets = value; } 
    } 
} 

लक्ष्य एक ग्राहक है:

public class Target:EntityBase 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string Note { get; set; } 
    public virtual Address Address { get; set; } 
    public virtual Customer Customer { get; set; } 
} 

ग्राहक एक व्यक्ति वर्ग से निकला है:

public class Person:EntityBase 
{   
    public string Salutation { get; set; } 
    public string Title { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set ; }   
    public string Telephone1 { get; set; } 
    public string Telephone2 { get; set; } 
    public string Email { get; set; }   

    public virtual Address Address { get; set; } 
} 

EntityBase वर्ग कुछ प्रदान करता है

एक ग्राहक एक या अधिक लक्ष्य है सामान्य गुण:

public abstract class EntityBase : INotifyPropertyChanged 
{ 
    public EntityBase() 
    { 
     CreateDate = DateTime.Now; 
     ChangeDate = CreateDate; 
     CreateUser = HttpContext.Current.User.Identity.Name; 
     ChangeUser = CreateUser; 
     PropertyChanged += EntityBase_PropertyChanged; 
    } 

    public void EntityBase_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (Id != new Guid()) 
     { 
      ChangeDate = DateTime.Now; 
      ChangeUser = HttpContext.Current.User.Identity.Name; 
     } 
    } 

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, e); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public Guid Id { get; set; } 
    public DateTime CreateDate { get; set; } 
    public DateTime? ChangeDate { get; set; } 
    public string CreateUser { get; set; } 
    public string ChangeUser { get; set; } 
} 

प्रसंग:

public class TgrDbContext : DbContext 
{ 
    public DbSet<Person> Persons { get; set; } 
    public DbSet<Address> Addresses { get; set; } 
    public DbSet<Customer> Customers { get; set; } 
    public DbSet<Target> Targets { get; set; } 
    public DbSet<ReportRequest> ReportRequests { get; set; } 

    // If OnModelCreating becomes to big, use "Model Configuration Classes" 
    //(derived from EntityTypeConfiguration) instead 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Person>().HasOptional(e => e.Address);    
     modelBuilder.Entity<Customer>().HasMany(c => c.Targets).WithRequired(t => t.Customer);    
    } 

    public static ObjectContext TgrObjectContext(TgrDbContext tgrDbContext) 
    {   
     return ((IObjectContextAdapter)tgrDbContext).ObjectContext; 
    } 
} 
+0

मेरे पास अगले 8 घंटों के भीतर उत्तर पोस्ट करने के लिए पर्याप्त अनुशंसा अंक नहीं हैं। जैसे ही यह संभव हो जाएगा पोस्ट करेंगे। – Martin

+0

यह बहुत चुनौतीपूर्ण है कि मैं इस समस्या के बारे में पूरे ब्लॉग पोस्ट पर काम कर रहा हूं (मैंने इसे लगभग दो महीने तक किया है लेकिन मैं अभी भी उससे पूरी तरह से संतुष्ट नहीं हूं)। कई पक्षों पर एक से कई संबंधों का अद्यतन शायद मुख्य कारण है कि क्यों विदेशी कुंजी संघों को लागू किया गया था (इस भयानक व्यवहार को ठीक करने के बजाय)। –

+0

मैं सहमत हूं। यह प्रक्रिया निश्चित रूप से होने की तुलना में निश्चित रूप से अधिक कठिन लगती है। फिर भी, ईएफ 4 और 4.1 पिछले संस्करणों में महत्वपूर्ण सुधार थे। ईएफ 4.1 के आस-पास के विषयों को खोजना सीटीपी और रिलीज संस्करणों के बीच एपीआई परिवर्तनों के कारण मुश्किल है, अलग-अलग बनाम जुड़े परिदृश्यों में अलग-अलग दृष्टिकोण, कई, अत्यधिक सरलीकृत नमूना अनुप्रयोग जो एन के साथ आने वाली अतिरिक्त जटिलता के लिए मार्गदर्शन प्रदान नहीं करते हैं -टेयर समाधान ... – Martin

उत्तर

5

मैं @ मार्टिन उत्तर के लिए इंतजार कर रहा था क्योंकि इस समस्या के लिए और अधिक समाधान हैं।

// Existing customer 
var customer = new Customer() { Id = customerId }; 
// Another existing customer 
var customer2 = new Customer() { Id = customerId2 }; 

var target = new Target { ID = oldTargetId }; 
// Make connection between target and old customer 
target.Customer = customer; 

// Attach target with old customer 
context.Targets.Attach(target); 
// Attach second customer 
context.Customers.Attach(customer2); 
// Set customer to a new value on attached object (it will delete old relation and add new one) 
target.Customer = customer2; 

// Change target's state to Modified 
context.Entry(target).State = EntityState.Modified; 
context.SaveChanges(); 

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

+0

आपके उत्तर, Ladislav के लिए धन्यवाद। आपका समाधान काम करता है और मैं इसे अपने ऊपर पसंद करता हूं क्योंकि आपके ऑब्जेक्ट कॉन्टेक्स्ट एपीआई के उपयोग की आवश्यकता नहीं है। सार्वजनिक शून्य अद्यतन लक्ष्य (लक्ष्य लक्ष्य, लक्ष्य मूल लक्ष्य) { { _tgrDbContext.Targets.Attach (origTarget); _tgrDbContext.Entry (origTarget) .Reload(); _tgrDbContext.Customers.Attach (target.Customer); _tgrDbContext.Entry (origTarget) .CurrentValues.SetValues ​​(लक्ष्य); origTarget.Customer = target.Customer; _tgrDbContext.Entry (origTarget) .State = EntityState.Modified; _tgrDbContext.SaveChanges(); } – Martin

+0

@ मार्टिन के समाधान को पसंद करें। यदि हमें 1-> 1 रिलाशिप को प्रतिस्थापित करने की आवश्यकता है तो आप हटाए गए कोड भाग को छोड़कर मार्टिन कोड चला सकते हैं। केवल 'EntityState.Added' लाइन की आवश्यकता है। क्या लाभ होगा? आपको पिछले बच्चे की वस्तु को जानने की आवश्यकता नहीं है। जो मेरी स्थिति में एक बहुत ही महत्वपूर्ण लाभ है। – Avrohom

4

वहाँ जानकारी का एक बहुत कुछ इस विषय पर पाया जा सकता है; स्टैकओवरफ्लो पर मैंने लाडस्लाव मिर्का की अंतर्दृष्टि विशेष रूप से सहायक पाया। इस विषय पर अधिक भी यहां पाया जा सकता: NTier Improvements for Entity Framework और यहाँ What's new in Entity Framework 4?

अपने प्रोजेक्ट में (Asp.Net वेबफ़ॉर्म) उपयोगकर्ता ग्राहक एक अलग (मौजूदा) ग्राहक वस्तु के साथ एक लक्ष्य वस्तु को सौंपा को बदलने के लिए विकल्प है। यह लेन-देन एक ऑब्जेक्टडेटा नियंत्रण से एक फॉर्म व्यू नियंत्रण द्वारा किया जाता है। ऑब्जेक्टडाटासोर्स प्रोजेक्ट की बिजनेस लॉजिक लेयर के साथ संचार करता है जो बदले में लेनदेन को डेटाएप परत में लक्ष्य ऑब्जेक्ट के लिए एक रिपॉजिटरी क्लास में पास करता है। भंडार वर्ग में लक्ष्य वस्तु के लिए अद्यतन विधि इस प्रकार है:

public void UpdateTarget(Target target, Target origTarget) 
    { 
     try 
     { 
      // It is not possible to handle updating one to many relationships (i.e. assign a 
      // different Customer to a Target) with "Independent Associations" in Code First. 
      // (It is possible when using "ForeignKey Associations" instead of "Independent 
      // Associations" but this brings about a different set of problems.) 
      // In order to update one to many relationships formed by "Independent Associations" 
      // it is necessary to resort to using the ObjectContext class (derived from an 
      // instance of DbContext) and 'manually' update the relationship between Target and Customer. 

      // Get ObjectContext from DbContext - ((IObjectContextAdapter)tgrDbContext).ObjectContext; 
      ObjectContext tgrObjectContext = TgrDbContext.TgrObjectContext(_tgrDbContext); 

      // Attach the original origTarget and update it with the current values contained in target 
      // This does NOT update changes that occurred in an "Independent Association"; if target 
      // has a different Customer assigned than origTarget this will go unrecognized 
      tgrObjectContext.AttachTo("Targets", origTarget); 
      tgrObjectContext.ApplyCurrentValues("Targets", target); 

      // This will take care of changes in an "Independent Association". A Customer has many 
      // Targets but any Target has exactly one Customer. Therefore the order of the two 
      // ChangeRelationshipState statements is important: Delete has to occur first, otherwise 
      // Target would have temporarily two Customers assigned. 
      tgrObjectContext.ObjectStateManager.ChangeRelationshipState(
       origTarget, 
       origTarget.Customer, 
       o => o.Customer, 
       EntityState.Deleted); 

      tgrObjectContext.ObjectStateManager.ChangeRelationshipState(
       origTarget, 
       target.Customer, 
       o => o.Customer, 
       EntityState.Added); 

      // Commit 
      tgrObjectContext.Refresh(RefreshMode.ClientWins, origTarget); 
      tgrObjectContext.SaveChanges(); 
     } 
     catch (Exception) 
     { 
      throw; 
     } 
    }    

इस लक्ष्य वस्तु के लिए अद्यतन विधि के लिए काम करता है। उल्लेखनीय है कि, एक नई लक्ष्य वस्तु डालने की प्रक्रिया आसान है। डीबीकॉन्टेक्स्ट स्वतंत्र सहयोग के ग्राहक अंत को सही ढंग से पहचानता है और आगे के बिना डेटाबेस में परिवर्तन करता है। भंडार वर्ग में सम्मिलित विधि इस प्रकार है:

 public void InsertTarget(Target target) 
    { 
     try 
     { 
      _tgrDbContext.Targets.Add(target); 
      _tgrDbContext.SaveChanges(); 
     } 
     catch (Exception) 
     { 
      throw; 
     } 
    } 

उम्मीद है कि इस एक समान कार्य के साथ काम कर किसी के लिए उपयोगी होगा। यदि आपको ऊपर वर्णित इस दृष्टिकोण के साथ कोई समस्या दिखाई देती है, तो कृपया मुझे अपनी टिप्पणियों में बताएं। धन्यवाद!

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