典型場景:Card 表關聯 CardKind 表,顯示列表時需要卡類型名稱而非 ID。若僅使用代碼生成器產出的表實體(僅含 CardKindId),將陷入「查詢 → 發現缺名稱 → 重寫 SQL Join → 綁定 → 詳情再查」的惡性循環。本文展示如何通過實體聚合一次性解決。
代碼生成器產出 Card、CardKind 兩獨立類,Card 僅持有 decimal CardKindId。列表 DTO 需 CardKindName,無法直接綁定。
public class Card
{
// 刪除原 CardKindId
// private decimal m_CardKindId;
// public decimal CardKindId { get; set; }
// 引入聚合對象
private CardKind m_CardKind;
public CardKind CardKind
{
get { return m_CardKind; }
set { m_CardKind = value; }
}
// 克隆需深拷貝聚合對象
public new Card Clone()
{
Card card = base.Clone() as Card;
card.m_CardKind = this.CardKind?.Clone(); // 假設 CardKind 實現 Clone
return card;
}
}
// SQL 使用 JOIN 一次取回所有字段
SELECT c.*, k.CardKindName, k.IsValid
FROM Card c
INNER JOIN CardKind k ON c.CardKindId = k.CardKindId
// 映射邏輯(伪代碼)
var card = new Card {
CardId = reader["CardId"],
StartNO = reader["StartNO"],
EndNO = reader["EndNO"],
CardKind = new CardKind {
CardKindId = reader["CardKindId"],
CardKindName = reader["CardKindName"],
IsValid = reader["IsValid"]
}
};
card.CardKind.CardKindName,無額外查詢。Card 擁有 CardKind,符合業務語義(一張卡「屬於」一種類型)。不要讓數據庫表結構直接決定領域模型。 表實體 ≠ 業務實體。聚合根(Aggregate Root)應封裝業務不變量與關聯導航,一次加載滿足多種使用場景。