Csla框架之业务对象状态

  (若感觉以下思想存在问题,请速速离开!)

  关于对象状态的维护,开始有所体会还是在linq2sql和ef中,称作上下文的应该就会对当前所使用过的对象进行状态跟踪,无论是新建对象,还是从数据库获取对象进而对其进行更新删除操作,在上下文中都会对它们进行状态跟踪。无论是简单对象还是包含子对象的复杂对象,都应该是有状态的。同样的思想,Csla框架中也是这么来处理的(当然,可以具体的处理方法不同)。

  Csla框架中,状态的管理只对可编辑的对象有用,包括可编辑的根、子对象,可编辑的根、子对象集,还有一个就是动态可编辑对象。对于只读的对象本身就不具可编辑性,所以也谈不上状态了。

  框架中的状态属性包括:IsNew,IsSelfDirty,IsDirty,IsSelfValid,IsValid,IsSavable,IsDeleted。其中在以前的版本中没有IsSelf与IsSelfValid,其展现形式是通过用户自己来实现的,在现在的版本中因为有了字段管理功能,所以这些功能就直接实现在了框架内部,比以前方便很多。也许从名称就可以看得出各个状态的意义,以下就个人看法作小小说明:

  (状态不会独立工作,有些状态的依据是来自于其他某些的状态,如IsDirty与IsSelfDirty有关,是否可保存状态IsSavable与IsDeleted,IsNew等多个状态有关(当然也可能与对象的IsBusy状态有关);在保存时以上多个状态都会先后起作用!)

  IsNew,顾名思义,代表新对象的意思,它标识如果内存中的对象主键存在于数据库中,那么值为False,否则值为True,在框架中创建新对象时默认为True,或者旧对象被删除后,系统也会将值赋予True(内在与数据库中主键不再对应)。在保存时,如果IsNew为True,系统会调用新增方法,否则就会是修改或删除。

  IsSelfDirty(这个属性在看2.0版本时还没有),标识对象创建/获取后是否对其数据进行更新过(书上称为脏对象),所以无论是新建对象时还是对象重获取时,对象的脏状态默认是False的,当对象在对对象属性进行赋值或通过方法间接操作时,脏属性就会标识为True。IsDirty与IsSelfDirty大体一致,但IsDirty的状态还会与它的子对象的状态相关,也就是只有对象自身的IsSelfDirty为False并且所有子对象的IsDirty的状态为False时此对象的IsDrity才为False,否则当前的对象就是标识为脏的,所以每次访问该属性时它都会去遍历它的所有子对象的状态(当然如果有为True的就会直接返回),这个功能在旧版本中是在对象中通过重写IsDirty来实现的,在现在的版本中框架通过字段管理就可以自动进行跟踪(前提是属性中的子对象是通过框架内部的字段管理方式来实现的)。因为在IsDirty为False时当前对象(及子对象)是未编辑状态,所以为True时系统才会继续向下根据其他状态判断该执行什么数据操作方法,

  IsValid与IsSelfValid与脏对象原理一致,只不过是否通过验证是根据对象的数据有效性有关,只有当前对象的所有字段都有效,也就是没有违反任何规则时才为True。数据有效性及验证规则的统一管理也是框架的一个实现目标,以后再说。

  IsDeleted,标识当前对象是否被删除。框架支持直接删除和延迟删除,是否删除属性就是延迟删除进行操作的依据(注意的是子对象的的删除方法是DeleteChild(),根对象的为Delete(),不通用!),它会将当前可编辑的对象标识为IsDeleted=True,系统并不会直接提交,而是作删除标记,当用户最后调用Save()方法时系统会根据当前对象或子对象的删除状态进行调用删除方法。

  最后的是IsSavable属性,它是以上属性的集合体,标识当前对象是否可保存,在这引用一下框架属性代码:

   1:          /// <summary>
   2:          /// Returns <see langword="true" /> if this object is both dirty and valid.
   3:          /// </summary>
   4:          /// <remarks>
   5:          /// An object is considered dirty (changed) if 
   6:          /// <see cref="P:Csla.BusinessBase.IsDirty" /> returns <see langword="true" />. It is
   7:          /// considered valid if IsValid
   8:          /// returns <see langword="true" />. The IsSavable property is
   9:          /// a combination of these two properties. 
  10:          /// </remarks>
  11:          /// <returns>A value indicating if this object is both dirty and valid.</returns>
  12:          [Browsable(false)]
  13:          public virtual bool IsSavable
  14:          {
  15:              get
  16:              {
  17:                  bool auth;
  18:                  if (IsDeleted)
  19:                      auth = Csla.Security.AuthorizationRules.CanDeleteObject(this.GetType());
  20:                  else if (IsNew)
  21:                      auth = Csla.Security.AuthorizationRules.CanCreateObject(this.GetType());
  22:                  else
  23:                      auth = Csla.Security.AuthorizationRules.CanEditObject(this.GetType());
  24:                  return (auth && IsDirty && IsValid && !IsBusy);
  25:              }
  26:          }

可以看出,除了上面的状态,还有auth和IsBusy,auth是获取对应状态下是否可操作的用户权限。至于后面的IsBusy,没注意过…

  属性的应用主要是在页面状态的控制与数据保存,如当对象IsSavable为False时让保存按钮失效,当对象是新对象时可以禁用掉删除按钮,还有个主要应用点就是保存时,上面也提到,下面也贴下代码:

   1:          /// <summary>
   2:          /// Saves the object to the database.
   3:          /// </summary>
   4:          /// <remarks>
   5:          /// <para>
   6:          /// Calling this method starts the save operation, causing the object
   7:          /// to be inserted, updated or deleted within the database based on the
   8:          /// object's current state.
   9:          /// </para><para>
  10:          /// If <see cref="Core.BusinessBase.IsDeleted" /> is <see langword="true"/>
  11:          /// the object will be deleted. Otherwise, if <see cref="Core.BusinessBase.IsNew" /> 
  12:          /// is <see langword="true"/> the object will be inserted. 
  13:          /// Otherwise the object's data will be updated in the database.
  14:          /// </para><para>
  15:          /// All this is contingent on <see cref="Core.BusinessBase.IsDirty" />. If
  16:          /// this value is <see langword="false"/>, no data operation occurs. 
  17:          /// It is also contingent on <see cref="Core.BusinessBase.IsValid" />. 
  18:          /// If this value is <see langword="false"/> an
  19:          /// exception will be thrown to indicate that the UI attempted to save an
  20:          /// invalid object.
  21:          /// </para><para>
  22:          /// It is important to note that this method returns a new version of the
  23:          /// business object that contains any data updated during the save operation.
  24:          /// You MUST update all object references to use this new version of the
  25:          /// business object in order to have access to the correct object data.
  26:          /// </para><para>
  27:          /// You can override this method to add your own custom behaviors to the save
  28:          /// operation. For instance, you may add some security checks to make sure
  29:          /// the user can save the object. If all security checks pass, you would then
  30:          /// invoke the base Save method via <c>base.Save()</c>.
  31:          /// </para>
  32:          /// </remarks>
  33:          /// <returns>A new object containing the saved values.</returns>
  34:          public virtual T Save()
  35:          {
  36:              T result;
  37:              if (this.IsChild)
  38:                  throw new NotSupportedException(Resources.NoSaveChildException);
  39:              if (EditLevel > 0)
  40:                  throw new Validation.ValidationException(Resources.NoSaveEditingException);
  41:              if (!IsValid && !IsDeleted)
  42:                  throw new Validation.ValidationException(Resources.NoSaveInvalidException);
  43:              if (IsBusy)
  44:                  throw new Validation.ValidationException(Resources.BusyObjectsMayNotBeSaved);
  45:              if (IsDirty)
  46:                  result = (T)DataPortal.Update(this);
  47:              else
  48:                  result = (T)this;
  49:              OnSaved(result, null, null);
  50:              return result;

 

  Over!

posted @ 2011-04-12 01:06  屈鲁奇  阅读(1308)  评论(0编辑  收藏  举报