2012-01-04 78 views
2

使用Ado.net自我跟踪实体生成器创建对象以维护状态跟踪器。对象是用户,培训师。培训师是用户中的子对象。当培训师修改信息时,它的状态会随着修改而改变。但用户对象仍然不变。我的要求是,当一个孩子对象被修改时,它必须与父对象亲密。如何使用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 2012-01-04 18:19:15

+0

由Ado.net自我跟踪实体生成器生成的代码是可用的在这个链接[url = http: //www.fileserve.com/file/nUwkHra/ControlLibrary.rar] [b]文件名:ControlLibrary.rar文件大小:15.97 KB [/ url] – VIJAY 2012-01-04 18:30:58

+0

个人不会下载你的.rar文件可能是由于他们的内部防火墙和安全性,所以粘贴什么代码是必要的,适用于你的问题。谢谢 – MethodMan 2012-01-04 18:34:28

回答

0

你不想这样做。这意味着当你有更复杂的对象图并且对象的某个实例发生了变化时,它将传播到所有位于上面的父母。这还不算什么问题。但是,对持久化实体应用对ObjectContext的更改时,FrameWork还会更新所有这些父项(当您的目标是将更改传播到父项的ChangeTracker - >ChangeTracker是由FrameWork用来检测更改的对象并发送更新,插入或删除查询到数据库)。

实体框架自身不包含自我跟踪实体的这种“级联”信息。

我们需要类似的功能。如果在底下发生了任何变化,可轻松检测到“顶级”对象。我们做了一个递归的方法来检查所有的基础实体和他们的ChangeTrackersState。注意:您可能不仅需要查看entity.ChangeTracker.State,还需要查看entity.ChangeTracker.AddedToCollectionPropertiesentity.ChangeTracker.RemovedFromCollectionProperties以查看是否有任何实体已添加或从导航属性中移除(基本上也是变化)。

另一种选择是在每个实体上包含一个简单的枚举(干净,修改,添加,删除等等),并在更改时更新实体上的Enum变量和上面的“父母”。这样你就不会干涉ChangeTracker,我不会惹得太多。

希望这会有所帮助。