Linq to SQL 產生的實體類別為自動產生程式碼,直接加上 Data Annotation 驗證屬性會在重新產生時遺失。本文示範 MetadataTypeAttribute 配合 Partial Class 與 Buddy Class 模式,將驗證邏輯剝離至獨立類別,實現「資料模型與驗證規則分離、重新產生不受影響、客戶端/伺服器端驗證雙贏」的最佳實踐。
// Linq to SQL 自動產生 (dbml -> .designer.cs)
public partial class Product
{
public string Name { get; set; }
public string Type { get; set; }
// 重新產生時,手動加上的 [Required] 會消失!
}
using System.ComponentModel.DataAnnotations;
public class ProductMetadata
{
[DisplayName("產品名稱")]
[Required(ErrorMessage = "請輸入產品名稱")]
[StringLength(50, ErrorMessage = "名稱長度不可超過 50 字元")]
public string Name { get; set; }
[DisplayName("產品類別")]
[Required(ErrorMessage = "請選擇類別")]
[StringLength(20, ErrorMessage = "類別長度不可超過 20 字元")]
public string Type { get; set; }
}
[MetadataType(typeof(ProductMetadata))]
public partial class Product
{
// 此處可擴充非驗證邏輯:計算屬性、業務方法等
public string FullInfo => $"{Name} ({Type})";
}
DataAnnotationsModelValidatorProvider) 在檢查模型型別時,會檢測 [MetadataType] 屬性。ProductMetadata) 的屬性與驗證屬性。若需針對不同情境 (建立/編輯/刪除) 套用不同驗證規則,可建立多個元資料類別,並在 Controller 動作中使用 ModelMetadataProviders.Current.GetMetadataForType 動態切換,或採用 FluentValidation 等更靈活的驗證框架。
只要 View 正確引用 jquery.validate.js、jquery.validate.unobtrusive.js,並使用 Html.EditorFor、Html.ValidationMessageFor,MVC 會自動輸出 data-val-* 屬性,無需額外程式碼即可啟用前端即時驗證。
FluentValidation 或 System.ComponentModel.Annotations 搭配 IValidatableObject。[MetadataType],相同模式可直接套用。MetadataType + Partial Class 是 Linq to SQL / EF Database-First 專案中,「保護自動產生代碼完整性」與「集中管理驗證規則」的經典模式。掌握此技巧,讓領域模型專注業務語義,驗證邏輯集中於 Buddy Class,重構與升級皆從容不迫。