2011-08-16 13 views
9

मैं एक आधार वर्ग कि मुझे लगता है कि से विरासत है दो शून्य अन्य संस्थाओं के साथ कई रिश्तों को:ChangeTracker इकाई की रूपरेखा 4.1 - संबंधित के मूल मान ऑब्जेक्ट्स

public abstract class WebObject 
{ 
    public WebObject() 
    { 
     RelatedTags = new List<Tag>(); 
     RelatedWebObjects = new List<WebObject>(); 
    } 

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public Guid Id { get; set; } 

    public string MetaKeywords { get; set; } 
    public string MetaDescription { get; set; } 

    [InverseProperty("WebObjects")] 
    public virtual WebSite WebSite { get; set; } 

    [Required(ErrorMessage = "Every WebObject must be associated with a WebSite.")] 
    public Guid WebSiteId { get; set; } 

    public virtual ICollection<Tag> RelatedTags { get; set; } 
    public IList<Guid> RelatedTagIds { get; set; } 
    public virtual ICollection<WebObject> RelatedWebObjects { get; set; } 
    public IList<Guid> RelatedWebObjectIds { get; set; } 
} 

मैं कठिनाई इन के लिए मूल मूल्यों हो रही हो रहा है रिश्ते (संबंधित वेबब्रेजेस & संबंधितटैग) SaveChanges के दौरान चेंजट्रैकर का उपयोग करते हुए इकाइयों को देखते समय। मैं पहले और बाद में सभी स्केलर मान देख सकता हूं, और मैं नए रिश्तों को देख सकता हूं, लेकिन मैं पुराने लोगों को नहीं देख सकता। मैंने सदस्य और संग्रह विधियों का उपयोग करने का प्रयास किया है, लेकिन वे केवल मुझे वर्तमान मूल्य दिखाते हैं; पुराना नहीं इसके अलावा मुझे उन लोगों का उपयोग करना पसंद नहीं है क्योंकि मुझे नेविगेशन संपत्ति का नाम जानना आवश्यक है, जो पर्याप्त सामान्य नहीं है।

मैं उन संबंधित वस्तुओं को ढूंढ सकता हूं जिनके रिश्ते को बदला जा रहा है, लेकिन निश्चित रूप से उन संबंधित वस्तुओं के मूल्यों में बदलाव नहीं हो रहा है, इसलिए यह कोई मदद नहीं है।

क्या चेंजट्रैकर के साथ SaveChanges के दौरान किसी इकाई के पिछले संबंधों को ट्रैक करने के लिए मेरे लिए कुछ साफ तरीका है?

नीचे है कि मैं पर काम कर रहा हूँ कोड की धारा है:

public override int SaveChanges() 
    { 
     List<AuditObject> auditTrailList = new List<AuditObject>(); 

     foreach (DbEntityEntry entity in ChangeTracker.Entries().Where(obj => { return obj.State == EntityState.Added || obj.State == EntityState.Modified || obj.State == EntityState.Deleted; })) 
     { 
      if (!(entity.Entity is AuditObject)) 
      { 
       AuditObject auditObject = new AuditObject(); 

       auditObject.Id = Guid.NewGuid(); 

       auditObject.RevisionStamp = DateTime.Now; 

       auditObject.UserName = HttpContext.Current.User.Identity.Name; 

       auditObject.EntityType = Utilities.GetCleanClassNameIfProxyClass(entity.Entity.GetType().Name); 

       if (entity.State == EntityState.Added) 
        auditObject.Action = EntityState.Added.ToString(); 
       else if (entity.State == EntityState.Modified) 
        auditObject.Action = EntityState.Modified.ToString(); 
       else if (entity.State == EntityState.Deleted) 
        auditObject.Action = EntityState.Deleted.ToString(); 

       DbMemberEntry t1 = entity.Member("RelatedWebObjects"); 
       // cannot find original relationship collection... 

       DbCollectionEntry t2 = entity.Collection("RelatedWebObjects"); 
       // cannot find original relationship collection... 

       if (entity.State == EntityState.Added || entity.State == EntityState.Modified) 
       { 
        XDocument currentValues = new XDocument(new XElement(auditObject.EntityType)); 

        foreach (string propertyName in entity.CurrentValues.PropertyNames) 
        { 
         currentValues.Root.Add(new XElement(propertyName, entity.CurrentValues[propertyName])); 
        } 

        auditObject.NewData = Regex.Replace(currentValues.ToString(), @"\r\n+", " "); 
       } 

       if (entity.State == EntityState.Modified || entity.State == EntityState.Deleted) 
       { 
        XDocument originalValues = new XDocument(new XElement(auditObject.EntityType)); 

        foreach (string propertyName in entity.OriginalValues.PropertyNames) 
        { 
         originalValues.Root.Add(new XElement(propertyName, entity.OriginalValues[propertyName])); 
        } 

        auditObject.OldData = Regex.Replace(originalValues.ToString(), @"\r\n+", " "); 
       } 

       auditTrailList.Add(auditObject); 
      } 
     } 

     foreach (var audit in auditTrailList) 
      this.AuditObjects.Add(audit); 

     return base.SaveChanges(); 
    } 
+0

संबंधित ऑब्जेक्ट्स को ऑब्जेक्टस्टेट प्रबंधक द्वारा ट्रैक किया जा रहा है और आप अपनी ऑब्जेक्ट स्टेट प्रविष्टियों को प्राप्त करने में सक्षम होना चाहिए जैसे कि आप इसे अपने मुख्य ऑब्जेक्ट के लिए कैसे प्राप्त करते हैं। यदि आप उस कोड को पोस्ट करते हैं जिसके साथ आप संघर्ष कर रहे हैं, तो मैं मदद कर सकता हूं। –

+0

धन्यवाद फिर से मोर्टेज़ा ... मैंने कोड के अनुभाग को पोस्ट किया है कि मैं अभी इस समय काम कर रहा हूं - कृपया इसकी ढीलीता से क्षमा करें; इसे बिल्कुल भी ठीक नहीं किया गया है - बस इसे काम करने की कोशिश कर रहा है। मैं आइटम्समेबल स्ट्रिंग्स का उपयोग कर किसी भी समस्या के बिना ऑब्जेक्ट्स के स्केलर गुण प्राप्त कर सकता हूं: entity.OriginalValues.PropertyNames & entity.CurrentValues.PropertyNames। मुझे इकाई के साथ परेशानी हो रही है। चयन() और इकाई। मेम्बर()। जो मैं पूरा करने की कोशिश कर रहा हूं उसके लिए उपयोग किया जाना चाहिए? क्या इस सामान्य को बनाने का कोई तरीका है ताकि मुझे संग्रह नामों को कड़ी-कोड करने की आवश्यकता न हो? प्रतिबिंब शायद? – DMC

+0

मैं कल तक इसे आजमाने की स्थिति में नहीं हूं ... क्या आप में से कोई भी जानता है कि मैं दो उत्तरों के बीच अंक कैसे विभाजित कर सकता हूं? क्योंकि मुझे लगता है कि आप दोनों ने बहुत मूल्यवान जानकारी दी है। – DMC

उत्तर

4

क्योंकि एफई परिवर्तन आपके ग्राफ में हर वस्तु को ट्रैक करता है, तो आप हमेशा किसी भी उदाहरण ग्राफ में बदलाव पर नजर के लिए पारित कर सकते हैं और कहीं भी होगी आपको परिवर्तन ट्रैकिंग मान दें। उदाहरण के लिए, निम्न कोड AuditObject के नेविगेशन संपत्ति के मूल/वर्तमान मूल्य मिलेगा:

DbMemberEntry t1 = entity.Member("RelatedWebObjects"); 
// cannot find original relationship collection.... 

AuditObject currentAuditObject = (AuditObject) entity; 
var currValues = this.Entry(currentAuditObject.RelatedWebObjects).CurrentValues; 
var orgValues = this.Entry(currentAuditObject.RelatedWebObjects).OriginalValues; 

या आप एक ही चाल है जब आप एक संग्रह प्रकार नेविगेशन संपत्ति के साथ काम कर रहे हैं लागू कर सकते हैं:

DbCollectionEntry t2 = entity.Collection("RelatedWebObjects"); 
// cannot find original relationship collection.... 

foreach (WebObject item in currentAuditObject.RelatedWebObjects) 
{ 
    var currValues = this.Entry(item).CurrentValues; 
} 
+0

धन्यवाद फिर भी मोर्टेज़ा! मैं आपको इतनी जल्दी वापस आने की सराहना करता हूं। ब्लॉग के लिए फिर भी धन्यवाद! – DMC

12

वैसे यह थोड़ा मुश्किल है। सबसे पहले आप two types of relationships एफई द्वारा की पेशकश की अलग करने के लिए है:

  • स्वतंत्र संघ (सभी कई-से-अनेक संबंध और कुछ एक-से-कई)
  • विदेशी कुंजी संघ (सभी एक-से-एक संबंध और कुछ एक-से-कई)

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

यदि आप एक स्वतंत्र संगठन में परिवर्तनों को ट्रैक करना चाहते हैं तो स्थिति कठिन हो जाएगी क्योंकि डीबीकॉन्टेक्स्ट एपीआई doesn't provide operations to track them। आपको ObjectContext एपीआई और इसके ObjectStateManager पर वापस जाना होगा।

ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; 
foreach (ObjectStateEntry entry = objectContext.ObjectStateManager 
               .GetObjectStateEntries(~EntityState.Detached) 
               .Where(e => e.IsRelationship)) 
{ 
    // Track changes here 
} 

अब आप रिश्ते के लिए ObjectStateEntry उदाहरणों की पहुंच है। इन उदाहरणों में राज्य Modified कभी नहीं होना चाहिए। वे या तो Added, Deleted या Unchanged होंगे क्योंकि "संशोधन" पुराने संबंधों को हटाने और एक नया जोड़ने के रूप में संसाधित किया जाता है। ObjectStateEntry में CurrentValues और OriginalValues संग्रह भी शामिल हैं। इन संग्रहों में संबंध के एक तरफ इकाई के EntityKey का प्रतिनिधित्व करने वाले दो आइटम भी हो सकते हैं।

+0

आपकी मदद के लिए बहुत बहुत धन्यवाद! मैं देख सकता हूं कि यह काम करता है। मैंने बिटवाई ~ ऑपरेटर के बारे में भी सीखा - पहले कभी इसका इस्तेमाल नहीं किया। क्या आपको पता है कि आप और मोर्टेज़ा दोनों को अंक असाइन करना संभव है? उसका जवाब पहले आया और काम करता है और मैं विशेष रूप से उनके ब्लॉग के माध्यम से उनके पास पहुंचा, लेकिन मैं चाहता हूं कि आप दोनों क्रेडिट प्राप्त करें ... – DMC

+0

@ डीएमसी: आप स्वीकार किए गए केवल एक ही जवाब को चिह्नित कर सकते हैं लेकिन आपकी प्रतिष्ठा के आधार पर आप भी कर सकते हैं जितना चाहें उतने उत्तरों के लिए अपवर्तित करें। –

+0

क्षमा करें - इसे मोर्टेज़ा को दे देंगे क्योंकि उसे पहले मिल गया था और मैं इसके बारे में सीधे उससे संपर्क करने के अपने रास्ते से बाहर गया। लेकिन मैंने आपको इसके लिए एक उपजाऊ दिया था। – DMC

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