先看應用程式如何應用驗證。以SalesOrderHeaderEntity為例子。
常見的三種驗證:
1)儲存之前的驗證,重寫ValidateEntityBeforeSave
2) 刪除前的驗證,重寫ValidateEntityBeforeDelete
3) 屬性擷取值之後的驗證,重寫ValidateFieldValue
先講解一個基本的模式,基類中的設計virtual方法,派生中中override,我們在運行時,會調用實際類型的方法
public class A
{
public virtual Do() { }
}
public class B: A
{
public override Do() { }
}
當以這種方法調用時
A obj=new B():
obj.Do();
它會根據obj的實際類型,調用對應的方法
驗證代碼的書寫
[Serializable]
public partial class SalesOrderHeaderValidator : ValidatorBase
{
// __LLBLGENPRO_USER_CODE_REGION_START ValidationCode
刪除採購單前的驗證,比如採購單還在被合約contact引用,則不允許刪除
public override void ValidateEntityBeforeDelete(IEntityCore involvedEntity)
{
base.ValidateEntityBeforeDelete(involvedEntity);
SalesOrderHeaderEntity salesOrder = (SalesOrderHeaderEntity)involvedEntity;
if (salesOrder.TotalDue != 0)
throw new Exception("Total due zero not allow for this period");
}
儲存採購單前的驗證,常常是驗證必須輸入值的欄位
public override void ValidateEntityBeforeSave(IEntityCore involvedEntity)
{
base.ValidateEntityBeforeSave(involvedEntity);
SalesOrderHeaderEntity salesOrder = (SalesOrderHeaderEntity)involvedEntity;
if(salesOrder.TaxAmt>1000)
throw new Exception("unable to deal with tax more than 1000");
}
採購單的屬性值發生改變時,應用此處的驗證,比如,當擷取到期日後,要驗證它不能小於當前日期
public override bool ValidateFieldValue(IEntityCore involvedEntity, int fieldIndex, object value)
{
bool result = base.ValidateFieldValue(involvedEntity, fieldIndex, value);
if (!result)
return false;
SalesOrderHeaderEntity salesOrder = (SalesOrderHeaderEntity)involvedEntity;
switch ((SalesOrderHeaderFieldIndex)fieldIndex)
{
case SalesOrderHeaderFieldIndex.DueDate:
return ValidateDueDate(salesOrder, (DateTime)value);
}
return true;
}
private bool ValidateDueDate(SalesOrderHeaderEntity salesOrder, DateTime value)
{
if(value.CompareTo(DateTime.Now) < 0)
throw new Exception("Due date cannot be less than today");
return true;
}
}
掛接到驗證代碼到實體中
重寫OnInitialized方法,給Validator 屬性指定驗證器
protected override void OnInitialized()
{
base.OnInitialized();
//Assign validator
this.Validator =new SalesOrderHeaderValidator();
}
追蹤刪除採購單的堆棧
先設計一個刪除的採購單的測試方法
[TestMethod]
public void TestDeleteSalesOrderHeader()
{
DataAccessAdapter adapter = new DataAccessAdapter(ConnectionString);
SalesOrderHeaderEntity salesOrder = new SalesOrderHeaderEntity(43659);
adapter.DeleteEntity(salesOrder);
}
進入DataAccessAdapterBase的方法
public bool DeleteEntity(IEntity2 entityToDelete)
{
return DeleteEntity(entityToDelete, null);
}
調用它的重載overload方法
public virtual bool DeleteEntity(IEntity2 entityToDelete, IPredicateExpression deleteRestriction)
{
EntityBase2 entityToDeleteAsEntityBase2 = (EntityBase2)entityToDelete;
entityToDeleteAsEntityBase2.CallValidateEntityBeforeDelete();
}
進入EntityBase2的CallValidateEntityBeforeDelete
internal void CallValidateEntityBeforeDelete()
{
OnValidateEntityBeforeDelete();
}
繼續進入OnValidateEntityBeforeDelete方法
protected virtual void OnValidateEntityBeforeDelete()
{
if( _validator != null )
{
_validator.ValidateEntityBeforeDelete( this );
}
}
至此就進入到了我在文章開頭寫的SalesOrderHeaderValidator的ValidateEntityBeforeDelete方法
再來看一下ValidatorBase 中的虛擬方法ValidateEntityBeforeDelete
[Serializable]
public abstract class ValidatorBase : IValidator
{
public virtual void ValidateEntityBeforeDelete( IEntityCore involvedEntity )
{
// nop
}
}
驗證屬性值
再來看屬性設定時的驗證,這種驗證方法可以驗證程式對採購單的任何屬性的複製行為。比如,商務規則是,任何時間,採購單的到期日都不能小於輸入採購單的當天,代碼如下,
SalesOrderHeaderEntity salesOrder = new SalesOrderHeaderEntity(2068);
salesOrder.DueDate = DateTime.Now.AddDays(-1); //這裡設定DueDate 的值為昨天,違反了商務規則
來追蹤它的堆棧,進入DueDate屬性的set方法
public virtual System.DateTime DueDate
{
set { SetValue((int)SalesOrderHeaderFieldIndex.DueDate, value); }
}
進入EntityBase2的SetValue方法
protected bool SetValue(int fieldIndex, object value)
{
return SetValue(fieldIndex, value, true);
}
同名的重載方法
protected bool SetValue(int fieldIndex, object value, bool performDesyncForFKFields)
{
// set value is not the same as the value to set, proceed
if(ValidateValue(fieldToSet, ref valueToSet, fieldIndex))
進入ValidateValue方法
private bool ValidateValue(IFieldInfo fieldToValidate, ref object value, int fieldIndex)
{
// perform custom validation.
validationResult = (OnValidateFieldValue(fieldIndex, value));
}
流程進入OnValidateFieldValue方法
protected virtual bool OnValidateFieldValue( int fieldIndex, object value )
{
bool returnValue = true;
if( _validator != null )
{
returnValue = _validator.ValidateFieldValue(this, fieldIndex, value );
}
return returnValue;
}
請注意看這一句returnValue = _validator.ValidateFieldValue(this, fieldIndex, value ),它會進入我在開頭重寫的ValidateFieldValue的方法裡面,最後就是進入自訂的方法ValidateDueDate
這就是驗證的完整堆棧流程。