首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Castle ActiveRecord 實戰(8):資料驗證完整指南——內建屬性、擴展機制與原理深度解析

     編輯:關於.NET

為什麼需要模型層驗證?

雖然 UI 層常做前端驗證,但模型層驗證是最後一道防線,確保資料完整性不因介面繞過。ActiveRecord 內建 ActiveRecordValidationBase 提供聲明式驗證,零配置整合 NHibernate 攔截器。

內建驗證屬性速查表

屬性用途範例
[ValidateNotEmpty]不可為空字串或 Null[Property, ValidateNotEmpty] public string Name
[ValidateEmail]Email 格式驗證[Property, ValidateEmail] public string Email
[ValidateRegExp]正則表達式驗證[Property, ValidateRegExp(@"\d{6}")] public string ZipCode
[ValidateIsUnique]資料庫唯一性檢查[Property, ValidateIsUnique] public string UserName
[ValidateConfirmation]兩欄位值一致(如密碼確認)[Property, ValidateConfirmation("Password")] public string ConfirmPassword

快速上手:三步驟啟用驗證

  1. 繼承基類:public class Custom : ActiveRecordValidationBase
  2. 標註屬性:在需驗證的 Property 加上對應 Attribute
  3. 呼叫驗證:if (entity.IsValid()) { ... } else { var errors = entity.ValidationErrorMessages; }
[ActiveRecord("Customs")]
public class Custom : ActiveRecordValidationBase {
    [PrimaryKey(PrimaryKeyType.Native)]
    public int ID { get; set; }

    [Property, ValidateNotEmpty]
    public string Name { get; set; }

    [Property, ValidateEmail]
    public string Email { get; set; }

    [Property, ValidateRegExp(@"\d{6}")]
    public string Post { get; set; }

    [Property, ValidateRegExp(@"(\(\d{3,4}\)|\d{3,4}-)?\d{8}")]
    public string Phone { get; set; }
}

單元測試驗證邏輯

[Test]
public void TestAllValidation() {
    var custom = new Custom {
        Name = "Terry Lee",
        Email = "lhj_cauc@hotmail.com",
        Phone = "022-24096335",
        Post = "300192"
    };
    Assert.IsTrue(custom.IsValid());
    Assert.AreEqual(0, custom.ValidationErrorMessages.Length);
}

[Test]
public void TestPostValidation() {
    var custom = new Custom {
        Name = "Terry Lee",
        Email = "invalid#mail.com",
        Post = "222t"
    };
    Assert.IsFalse(custom.IsValid());
    Assert.AreEqual(2, custom.ValidationErrorMessages.Length); // Email + Post 失敗
}

擴展自訂驗證:實作 AbstractValidator 與 AbstractValidationAttribute

類別結構:

  • AbstractValidationAttribute:標註在 Property 上,持有 Validator 實例
  • AbstractValidator:實作 IValidator,核心邏輯在 Perform(object instance, object fieldValue)

範例:自訂「大於零」驗證

[Serializable]
public class ValidatePositiveAttribute : AbstractValidationAttribute {
    public ValidatePositiveAttribute() : base(new PositiveValidator()) { }
    public ValidatePositiveAttribute(string errorMessage) : base(new PositiveValidator(), errorMessage) { }
}

[Serializable]
public class PositiveValidator : AbstractValidator {
    public override bool Perform(object instance, object fieldValue) {
        if (fieldValue == null) return false;
        return Convert.ToDecimal(fieldValue) > 0;
    }
    protected override string BuildErrorMessage() {
        return $"{Property.Name} 必須大於零";
    }
}
// 使用
[Property, ValidatePositive]
public decimal Amount { get; set; }

原理深度剖析:驗證流程與攔截時機

  1. 初始化收集:ActiveRecordValidationBase 建構子呼叫 CollectValidators(),透過 ActiveRecordModel 掃描所有 Property 上的 AbstractValidationAttribute,取出對應 Validator 存入 ArrayList __validators。
  2. 驗證執行:呼叫 IsValid() 時,逐一呼叫 validator.Perform(this)(傳入實體本身),失敗則收集 validator.ErrorMessage 至陣列。
  3. 攔截整合:ActiveRecord 內部攔截 OnSave/OnUpdate/OnDelete,自動呼叫 IsValid(),驗證失敗拋出 ValidationException 並回滾交易。

進階用法:ShouldLog 機制避免昂貴驗證成本

若驗證涉及昂貴運算(如遠端 API 呼叫),可先用 Logger.ShouldLog(logEntry) 預檢是否會被過濾,決定是否執行完整驗證邏輯。

總結

ActiveRecord 驗證框架提供開箱即用的聲明式驗證,支援擴展且整合交易攔截。善用內建屬性覆蓋 80% 場景,複雜規則透過自訂 Validator 封裝,保持模型純淨與職責單一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved