2012-01-04 3 views
2

상태 추적기를 유지 관리하기 위해 Ado.net 자체 추적 엔터티 생성기를 사용하여 만든 개체. 개체는 사용자, 강사입니다. 강사는 사용자의 자식 개체입니다. Trainer에서 수정 된 정보는 변경된 상태로 변경됩니다. 그러나 사용자 오브젝트는 여전히 변경되지 않습니다. 내 요구 사항은 언제든지 자식 개체가 부모 개체에 친숙해야만하는 경우입니다.ObjectWithChangeTracker를 사용하여 부모 개체에 자식 개체 수정을 알리는 방법

User.cs

//------------------------------------------------------------------------------ 
// <auto-generated> 
//  This code was generated from a template. 
// 
//  Changes to this file may cause incorrect behavior and will be lost if 
//  the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Collections.Specialized; 
using System.ComponentModel; 
using System.Globalization; 
using System.Runtime.Serialization; 

namespace ControlLibrary 
{ 
    [DataContract(IsReference = true)] 
    [KnownType(typeof(Trainer))] 
    public partial class User: IObjectWithChangeTracker, INotifyPropertyChanged 
    { 
     #region Primitive Properties 

     [DataMember] 
     public int UserId 
     { 
      get { return _userId; } 
      set 
      { 
       if (_userId != value) 
       { 
        if (ChangeTracker.ChangeTrackingEnabled && ChangeTracker.State != ObjectState.Added) 
        { 
         throw new InvalidOperationException("The property 'UserId' is part of the object's key and cannot be changed. Changes to key properties can only be made when the object is not being tracked or is in the Added state."); 
        } 
        _userId = value; 
        OnPropertyChanged("UserId"); 
       } 
      } 
     } 
     private int _userId; 

     [DataMember] 
     public string UserName 
     { 
      get { return _userName; } 
      set 
      { 
       if (_userName != value) 
       { 
        _userName = value; 
        OnPropertyChanged("UserName"); 
       } 
      } 
     } 
     private string _userName; 

     #endregion 
     #region Navigation Properties 

     [DataMember] 
     public Trainer Trainer 
     { 
      get { return _trainer; } 
      set 
      { 
       if (!ReferenceEquals(_trainer, value)) 
       { 
        var previousValue = _trainer; 
        _trainer = value; 
        FixupTrainer(previousValue); 
        OnNavigationPropertyChanged("Trainer"); 
       } 
      } 
     } 
     private Trainer _trainer; 

     #endregion 
     #region ChangeTracking 

     protected virtual void OnPropertyChanged(String propertyName) 
     { 
      if (ChangeTracker.State != ObjectState.Added && ChangeTracker.State != ObjectState.Deleted) 
      { 
       ChangeTracker.State = ObjectState.Modified; 
      } 
      if (_propertyChanged != null) 
      { 
       _propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     protected virtual void OnNavigationPropertyChanged(String propertyName) 
     { 
      if (_propertyChanged != null) 
      { 
       _propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged{ add { _propertyChanged += value; } remove { _propertyChanged -= value; } } 
     private event PropertyChangedEventHandler _propertyChanged; 
     private ObjectChangeTracker _changeTracker; 

     [DataMember] 
     public ObjectChangeTracker ChangeTracker 
     { 
      get 
      { 
       if (_changeTracker == null) 
       { 
        _changeTracker = new ObjectChangeTracker(); 
        _changeTracker.ObjectStateChanging += HandleObjectStateChanging; 
       } 
       return _changeTracker; 
      } 
      set 
      { 
       if(_changeTracker != null) 
       { 
        _changeTracker.ObjectStateChanging -= HandleObjectStateChanging; 
       } 
       _changeTracker = value; 
       if(_changeTracker != null) 
       { 
        _changeTracker.ObjectStateChanging += HandleObjectStateChanging; 
       } 
      } 
     } 

     private void HandleObjectStateChanging(object sender, ObjectStateChangingEventArgs e) 
     { 
      if (e.NewState == ObjectState.Deleted) 
      { 
       ClearNavigationProperties(); 
      } 
     } 

     protected bool IsDeserializing { get; private set; } 

     [OnDeserializing] 
     public void OnDeserializingMethod(StreamingContext context) 
     { 
      IsDeserializing = true; 
     } 

     [OnDeserialized] 
     public void OnDeserializedMethod(StreamingContext context) 
     { 
      IsDeserializing = false; 
      ChangeTracker.ChangeTrackingEnabled = true; 
     } 

     protected virtual void ClearNavigationProperties() 
     { 
      Trainer = null; 
     } 

     #endregion 
     #region Association Fixup 

     private void FixupTrainer(Trainer previousValue) 
     { 
      // This is the principal end in an association that performs cascade deletes. 
      // Update the event listener to refer to the new dependent. 
      if (previousValue != null) 
      { 
       ChangeTracker.ObjectStateChanging -= previousValue.HandleCascadeDelete; 
      } 

      if (Trainer != null) 
      { 
       ChangeTracker.ObjectStateChanging += Trainer.HandleCascadeDelete; 
      } 

      if (IsDeserializing) 
      { 
       return; 
      } 

      if (previousValue != null && ReferenceEquals(previousValue.User, this)) 
      { 
       previousValue.User = null; 
      } 

      if (Trainer != null) 
      { 
       Trainer.User = this; 
      } 

      if (ChangeTracker.ChangeTrackingEnabled) 
      { 
       if (ChangeTracker.OriginalValues.ContainsKey("Trainer") 
        && (ChangeTracker.OriginalValues["Trainer"] == Trainer)) 
       { 
        ChangeTracker.OriginalValues.Remove("Trainer"); 
       } 
       else 
       { 
        ChangeTracker.RecordOriginalValue("Trainer", previousValue); 
        // This is the principal end of an identifying association, so the dependent must be deleted when the relationship is removed. 
        // If the current state of the dependent is Added, the relationship can be changed without causing the dependent to be deleted. 
        if (previousValue != null && previousValue.ChangeTracker.State != ObjectState.Added) 
        { 
         previousValue.MarkAsDeleted(); 
        } 
       } 
       if (Trainer != null && !Trainer.ChangeTracker.ChangeTrackingEnabled) 
       { 
        Trainer.StartTracking(); 
       } 
      } 
     } 

     #endregion 
    } 
} 

Trainer.cs 파일은이 작업을 수행하지 않으려는

//------------------------------------------------------------------------------ 
// <auto-generated> 
//  This code was generated from a template. 
// 
//  Changes to this file may cause incorrect behavior and will be lost if 
//  the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Collections.Specialized; 
using System.ComponentModel; 
using System.Globalization; 
using System.Runtime.Serialization; 

namespace ControlLibrary 
{ 
    [DataContract(IsReference = true)] 
    [KnownType(typeof(User))] 
    public partial class Trainer: IObjectWithChangeTracker, INotifyPropertyChanged 
    { 
     #region Primitive Properties 

     [DataMember] 
     public int TrainerId 
     { 
      get { return _trainerId; } 
      set 
      { 
       if (_trainerId != value) 
       { 
        if (ChangeTracker.ChangeTrackingEnabled && ChangeTracker.State != ObjectState.Added) 
        { 
         throw new InvalidOperationException("The property 'TrainerId' is part of the object's key and cannot be changed. Changes to key properties can only be made when the object is not being tracked or is in the Added state."); 
        } 
        if (!IsDeserializing) 
        { 
         if (User != null && User.UserId != value) 
         { 
          User = null; 
         } 
        } 
        _trainerId = value; 
        OnPropertyChanged("TrainerId"); 
       } 
      } 
     } 
     private int _trainerId; 

     [DataMember] 
     public int UserId 
     { 
      get { return _userId; } 
      set 
      { 
       if (_userId != value) 
       { 
        _userId = value; 
        OnPropertyChanged("UserId"); 
       } 
      } 
     } 
     private int _userId; 

     [DataMember] 
     public Nullable<bool> IsFloorTrainer 
     { 
      get { return _isFloorTrainer; } 
      set 
      { 
       if (_isFloorTrainer != value) 
       { 
        _isFloorTrainer = value; 
        OnPropertyChanged("IsFloorTrainer"); 
       } 
      } 
     } 
     private Nullable<bool> _isFloorTrainer; 

     #endregion 
     #region Navigation Properties 

     [DataMember] 
     public User User 
     { 
      get { return _user; } 
      set 
      { 
       if (!ReferenceEquals(_user, value)) 
       { 
        if (ChangeTracker.ChangeTrackingEnabled && ChangeTracker.State != ObjectState.Added && value != null) 
        { 
         // This the dependent end of an identifying relationship, so the principal end cannot be changed if it is already set, 
         // otherwise it can only be set to an entity with a primary key that is the same value as the dependent's foreign key. 
         if (TrainerId != value.UserId) 
         { 
          throw new InvalidOperationException("The principal end of an identifying relationship can only be changed when the dependent end is in the Added state."); 
         } 
        } 
        var previousValue = _user; 
        _user = value; 
        FixupUser(previousValue); 
        OnNavigationPropertyChanged("User"); 
       } 
      } 
     } 
     private User _user; 

     #endregion 
     #region ChangeTracking 

     protected virtual void OnPropertyChanged(String propertyName) 
     { 
      if (ChangeTracker.State != ObjectState.Added && ChangeTracker.State != ObjectState.Deleted) 
      { 
       ChangeTracker.State = ObjectState.Modified; 
      } 
      if (_propertyChanged != null) 
      { 
       _propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     protected virtual void OnNavigationPropertyChanged(String propertyName) 
     { 
      if (_propertyChanged != null) 
      { 
       _propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged{ add { _propertyChanged += value; } remove { _propertyChanged -= value; } } 
     private event PropertyChangedEventHandler _propertyChanged; 
     private ObjectChangeTracker _changeTracker; 

     [DataMember] 
     public ObjectChangeTracker ChangeTracker 
     { 
      get 
      { 
       if (_changeTracker == null) 
       { 
        _changeTracker = new ObjectChangeTracker(); 
        _changeTracker.ObjectStateChanging += HandleObjectStateChanging; 
       } 
       return _changeTracker; 
      } 
      set 
      { 
       if(_changeTracker != null) 
       { 
        _changeTracker.ObjectStateChanging -= HandleObjectStateChanging; 
       } 
       _changeTracker = value; 
       if(_changeTracker != null) 
       { 
        _changeTracker.ObjectStateChanging += HandleObjectStateChanging; 
       } 
      } 
     } 

     private void HandleObjectStateChanging(object sender, ObjectStateChangingEventArgs e) 
     { 
      if (e.NewState == ObjectState.Deleted) 
      { 
       ClearNavigationProperties(); 
      } 
     } 

     protected bool IsDeserializing { get; private set; } 

     [OnDeserializing] 
     public void OnDeserializingMethod(StreamingContext context) 
     { 
      IsDeserializing = true; 
     } 

     [OnDeserialized] 
     public void OnDeserializedMethod(StreamingContext context) 
     { 
      IsDeserializing = false; 
      ChangeTracker.ChangeTrackingEnabled = true; 
     } 

     // This entity type is the dependent end in at least one association that performs cascade deletes. 
     // This event handler will process notifications that occur when the principal end is deleted. 
     internal void HandleCascadeDelete(object sender, ObjectStateChangingEventArgs e) 
     { 
      if (e.NewState == ObjectState.Deleted) 
      { 
       this.MarkAsDeleted(); 
      } 
     } 

     protected virtual void ClearNavigationProperties() 
     { 
      User = null; 
     } 

     #endregion 
     #region Association Fixup 

     private void FixupUser(User previousValue) 
     { 
      if (IsDeserializing) 
      { 
       return; 
      } 

      if (previousValue != null && ReferenceEquals(previousValue.Trainer, this)) 
      { 
       previousValue.Trainer = null; 
      } 

      if (User != null) 
      { 
       User.Trainer = this; 
       TrainerId = User.UserId; 
      } 

      if (ChangeTracker.ChangeTrackingEnabled) 
      { 
       if (ChangeTracker.OriginalValues.ContainsKey("User") 
        && (ChangeTracker.OriginalValues["User"] == User)) 
       { 
        ChangeTracker.OriginalValues.Remove("User"); 
       } 
       else 
       { 
        ChangeTracker.RecordOriginalValue("User", previousValue); 
       } 
       if (User != null && !User.ChangeTracker.ChangeTrackingEnabled) 
       { 
        User.StartTracking(); 
       } 
      } 
     } 

     #endregion 
    } 
} 
+0

코드 예제가 있습니까? 이벤트 추가 또는 상위/하위 이벤트 처리를 위임하거나 AnonymousDelegate 만들기 – MethodMan

+0

Ado.net 셀프 추적 엔티티 생성 프로그램에서 생성 된 코드는이 링크에서 사용할 수 있습니다 [url = http : //www.fileserve.com/file/nUwkHra/ControlLibrary.rar][b] 파일 이름 : ControlLibrary.rar 파일 크기 : 15.97 KB [/ b] [/ url] – VIJAY

+0

개인은 .rar 파일을 다운로드하지 않습니다. 그들의 내부 방화벽 및 보안 그래서 어떤 코드가 필요하고 귀하의 질문에 적용 할 붙여 넣습니다. 감사합니다 – MethodMan

답변

0

입니다. 더 복잡한 개체 그래프가 있고 개체의 일부 인스턴스가 변경되면이 개체는 위의 모든 부모에게 전파 될 것입니다. 그것은 여전히 ​​많은 문제가 아닙니다. 그러나 지속 엔티티에 대해 ObjectContext에 변경 사항을 적용하면 FrameWork는 해당 부모를 모두 업데이트합니다 (대상이 부모의 ChangeTracker에 변경 내용을 전파 할 때) - ChangeTracker은 FrameWork가 변경 사항을 감지하는 데 사용하는 객체입니다 데이터베이스에 쿼리를 업데이트, 삽입 또는 삭제).

Entity Framework는 자체 추적 엔터티에 대해 이러한 종류의 "계단식"정보를 포함하지 않습니다.

비슷한 기능이 필요했습니다. 무엇인가가 바뀌면 "최상위"객체를 쉽게 감지 할 수 있습니다. 우리는 모든 기본 엔티티를 확인하는 재귀 적 방법을 만들었으며 StateChangeTrackers입니다. 주의 사항 : entity.ChangeTracker.State을 보면서 entity.ChangeTracker.AddedToCollectionPropertiesentity.ChangeTracker.RemovedFromCollectionProperties을보아야 만 탐색 속성 (기본적으로 변경되는 항목)에 항목이 추가되거나 제거되었는지 확인할 수 있습니다.

또 다른 옵션은 모든 엔티티에 간단한 Enum (Clean, Modified, Added, Deleted 등 ...)을 포함시키는 것입니다. 그리고 변경이 이루어지면 엔티티와 위의 "부모"에 대한 Enum 변수를 업데이트하십시오. 이렇게하면 너무 많이 혼란하지 않을 ChangeTracker를 방해하지 않습니다.

희망이 도움이됩니다.

관련 문제