第 2 部分:建立領域模型
作者:Rick Anderson
加入模型
有三種方式可使用 Entity Framework:
- 資料庫優先:您從資料庫開始,Entity Framework 會產生程式碼。
- 模型優先:您從視覺模型開始,而 Entity Framework 會產生資料庫和程式碼。
- 程式碼優先:您從程式碼開始,Entity Framework 會產生資料庫。
我們使用的是程式碼優先方法,因此首先將領域物件定義為 POCO (單純的 CLR 物件)。 使用程式碼優先方法時,領域物件不需要任何額外的程式碼來支援資料庫層,例如交易或持續性。 (具體來說,他們不需要繼承自 EntityObject 類別。) 您仍然可以使用資料註釋來控制 Entity Framework 建立資料庫架構的方法。
由於 POCO 不會攜帶任何描述資料庫狀態的額外屬性,因此可以輕鬆地序列化為 JSON 或 XML。 不過,這不表示您應該一律將 Entity Framework 模型直接公開給用戶端,如稍後在本教學課程中所示。
我們將建立下列 POCO:
- Products
- 訂單
- OrderDetail
若要建立每個類別,請在 [方案總管] 中,以滑鼠右鍵按一下 [模型] 資料夾。 從操作功能表中,選取 [新增],然後選取 [類別]。
使用下列實作新增 Product
類別:
namespace ProductStore.Models
{
using System.ComponentModel.DataAnnotations;
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; }
}
}
根據慣例,Entity Framework 會使用 Id
屬性做為主要索引鍵,並將它對應至資料庫資料表中的識別欄位。 當您建立新的 Product
執行個體時,將不會設定 Id
的值,因為資料庫會產生值。
ScaffoldColumn 屬性會告訴 ASP.NET MVC 在產生編輯器表單時略過 Id
屬性。 Required 屬性是用來驗證模型。 它會指定 Name
屬性必須是非空白字串。
新增 Order
類別:
namespace ProductStore.Models
{
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public class Order
{
public int Id { get; set; }
[Required]
public string Customer { get; set; }
// Navigation property
public ICollection<OrderDetail> OrderDetails { get; set; }
}
}
新增 OrderDetail
類別:
namespace ProductStore.Models
{
public class OrderDetail
{
public int Id { get; set; }
public int Quantity { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
// Navigation properties
public Product Product { get; set; }
public Order Order { get; set; }
}
}
外部索引鍵關聯性
訂單包含許多訂單詳細資料,而每個訂單詳細資料則指稱單一產品。 為了表示這些關聯性,OrderDetail
類別會定義名為 OrderId
和 ProductId
的屬性。 Entity Framework 會推斷這些屬性代表外部索引鍵,並將外部索引鍵約束條件新增至資料庫。
Order
和 OrderDetail
類別也包含「navigation」屬性,其中包含相關物件的參考。 根據訂單,您可以遵循導覽屬性,依序瀏覽至產品。
立即編譯專案。 Entity Framework 會使用反映來探索模型的屬性,因此需要編譯的組件才能建立資料庫架構。
設定媒體類型格式器
當 Web API 寫入 HTTP 回應本文時,媒體類型格式器是序列化資料的物件。 內建格式器支援 JSON 和 XML 輸出。 根據預設,這兩個格式器都會依值序列化所有物件。
如果物件圖形包含循環參考,依值序列化會產生問題。 這正是 Order
和 OrderDetail
類別的情況,因為每個類別都有另一個的參考。 格式器會遵循參考、依值寫入每個物件,並以圓形為單位。 因此,我們需要變更預設行為。
在 [方案總管] 中,展開 [App_Start] 資料夾,然後開啟名為 WebApiConfig.cs 的檔案。 將下列程式碼新增至 WebApiConfig
類別:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// New code:
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
}
}
此程式碼會將 JSON 格式器設定為保留物件參考,並完全從管線中移除 XML 格式器。 (您可以將 XML 格式器設定為保留物件參考,但還需要多一點操作,且此應用程式只需要 JSON。如需詳細資訊,請參閱處理循環物件參考。)