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

ASP.NET Web API 教學 (0) 建立領域模型:POCO 設計、Code First 外鍵關聯與 JSON 循環參考解決

     編輯:ASP.NET 基礎

Entity Framework 三種開發模式

模式起點產出
Database First既有資料庫程式碼 (EDMX → TT 模板)
Model First視覺化設計師 (EDMX)資料庫 + 程式碼
Code First (本教學)POCO 類別資料庫 (自動建立/遷移)

Code First 最大優勢:領域模型純淨 (POCO),無基底類別綁定,易測試、易序列化 (JSON/XML)。

POCO 類別定義

// Product.cs
public class Product
{
    [ScaffoldColumn(false)] public int Id { get; set; }
    [Required] public string Name { get; set; }
    public decimal Price { get; set; }
    public decimal ActualCost { get; set; }
}

// Order.cs
public class Order
{
    public int Id { get; set; }
    [Required] public string Customer { get; set; }
    public virtual ICollection<OrderDetail> OrderDetails { get; set; } // 導航屬性
}

// OrderDetail.cs
public class OrderDetail
{
    public int Id { get; set; }
    public int Quantity { get; set; }
    public int OrderId { get; set; }   // 外鍵
    public int ProductId { get; set; } // 外鍵
    public virtual Product Product { get; set; } // 導航屬性
    public virtual Order Order { get; set; }
}
  • Id 慣例對應 Identity 主鍵,資料庫自動產生。
  • [ScaffoldColumn(false)]:MVC 編輯樣板隱藏此欄位。
  • [Required]:模型驗證必填。
  • virtual:啟用 EF 延遲載入。
  • 外鍵慣例:OrderId、ProductId 自動對應關聯。

外鍵關聯圖示

Order (1) ─────< (多) OrderDetail (多) ─────> (1) Product
  │                                       ▲
  └────────────── 導航屬性 ───────────────┘

EF 會自動在資料庫建立 Foreign Key Constraints。

編譯專案 (重要)

EF 使用反射掃描模型屬性,**必須先建置專案**產生組件,否則「新增控制器」對話框的模型類別下拉會是空的。

Media-Type Formatter 設定:解決循環參考

Order.OrderDetails → OrderDetail.Order 形成雙向循環,預設 JSON 序列化會無限遞迴拋出例外。修改 App_Start/WebApiConfig.cs:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });

        // 關鍵:保留物件參考 ($id/$ref)
        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;

        // 僅需 JSON,移除 XML Formatter 減少管線開銷
        config.Formatters.Remove(config.Formatters.XmlFormatter);
    }
}

序列化結果範例:

[
  { "$id": "1", "Id": 1, "Customer": "Bob", "OrderDetails": [
    { "$id": "2", "Quantity": 2, "Order": { "$ref": "1" }, "Product": { "$id": "3", "Name": "Tomato Soup" } }
  ]}
]

$id 標記物件身分,$ref 參考既有物件,完美解決循環。

替代方案比較

方案優點缺點
PreserveReferencesHandling.Objects (本文)零代碼修改模型、完整保留圖結構JSON 體積稍大、非標準 JSON (需 Newtonsoft 解析)
DTO/ViewModel 扁平化標準 JSON、前端友善、解耦領域模型需手寫映射代碼 (可用 AutoMapper)
[JsonIgnore] 忽略反向導航簡單失去反向導航資訊、序列化不完整
建議:內部 API 用 PreserveReferences;對外公開 API 必須用 DTO 扁平化,確保穩定契約。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved