讓我先說這個問題,並說明使用實體框架不適合我們。企業中企業實體驗證的首選方法
在我們的財務組織中,我們有跨越解決方案的業務實體。有些人擁有其他人不需要的界面。驗證和業務規則必須包含在實體中。
我針對爲我生成的DAL和DTO編寫代碼,這些DAL使用procs在數據庫上運行CRUD(可能是SQL可能是Oracle)。
因此,當我創建MVC,WCF,控制檯應用程序等。如果可以實現更好的驗證方法,問題一直在嘮叨。
這裏是一個實體對象一個典型的幾個特性:
[DefaultValue("")]
public string Branch {
get { return _branch; }
set {
if (value != null && value == _branch) return;
const string propertyName = "Branch";
ValidationInstance.Clear(propertyName);
ValidationInstance.ValidateRequired(propertyName, value);
ValidationInstance.ValidateNumeric(propertyName, value);
ValidationInstance.ValidateLength(propertyName, value, 2);
_branch = value;
if (EntityState != EntityStateType.New)
EntityState = EntityStateType.Changed;
}
}
[DefaultValue(0)]
public decimal HighDefermentMargin {
get { return _highDefermentMargin; }
set {
if (value == _highDefermentMargin) return;
const string propertyName = "HighDefermentMargin";
ValidationInstance.Clear(propertyName);
ValidationInstance.ValidateRange(propertyName, value);
_highDefermentMargin = value;
if (EntityState != EntityStateType.New)
EntityState = EntityStateType.Changed;
}
}
正如你可以看到有進行越來越詳細的驗證數據註釋和顯式調用驗證類的組合。
在一個MVC應用程序中,我們在ViewModel上苦心地複製了驗證,因此我們獲得了客戶端和服務器端的驗證。這裏是同一屬性的視圖模型版本從上面:
[Required]
[Range(0.0, 99.99)]
[Display(Name = "High Deferment Margin")]
public decimal HighDefermentMargin { get; set; }
這裏的主要區別是,在實體驗證加載錯誤插入的驗證類的錯誤集合,可以在當時的實體進行查詢去拯救自己。如果(!IsValid)則拋出一個包含錯誤數組的自定義異常。控制器通過它們循環並將它們添加到ModelState中。
我開始研究一些幾乎有幾百個字段的類。即使它們被面向對象分解,領域的數量仍然非常高。這些都是貸款認證等,對於單個記錄有很多數據。必須寫出對許多屬性的驗證使我想吐。我不能只編寫一個實用程序來生成實體和驗證,因爲業務規則是驅動驗證的原因,而不是數據庫。這意味着一個字段在數據庫中可以爲空,但不允許根據業務規則保留爲空值,或者該字段可以爲空,但只有在單獨的字段具有值時纔是空的等。
所以,可以使用just View Model中的數據註釋與實體的實現方式是否相同?我可以爲非標準驗證編寫自定義驗證器,然後爲更復雜的內容編寫業務規則。驗證錯誤是否會從實體中獲得更高的級別,以便UI可以像ModelState一樣以友好的方式通知用戶?其他人在這種情況下做什麼?
我有一個建議。在遇到無效輸入或在通過業務規則引擎進行驗證時規則未滿足的任何情況下,只需冒泡該異常,以便可以在Controller中捕獲該異常,然後將其添加到modelstate的錯誤集合中。例如:拋出一個自定義的異常,並且不要在規則引擎中捕獲該異常,只需重新拋出,直到它到達控制器。然後使用Html.ValidationSummary()在UI中顯示。 – Saravanan 2012-03-16 03:50:01
這樣做會奏效 - 但這個想法是爲了避免評估集合中的屬性或獲取並提供更多的AoP設計模式。我已經在房產中找到了收集錯誤的策略。所有拋出異常都會提供一種不同的方式來向調用者顯示錯誤。這只是交換不同代碼的代碼。我想消除屬性中的代碼。 – 2012-03-16 14:09:53
內置的類型默認爲必需,您不需要添加該屬性。 – RickAndMSFT 2012-03-22 17:07:05