第 2 部分:创建域模型
作者:Rick Anderson
添加模型
可通过三种方法处理实体框架:
- 数据库优先:从数据库开始,实体框架生成代码。
- 模型优先:从视觉对象模型开始,实体框架将生成数据库和代码。
- 代码优先:从代码开始,实体框架生成数据库。
我们使用的是代码优先方法,因此首先将域对象定义为 POCO (普通旧 CLR 对象) 。 使用代码优先方法时,域对象不需要任何额外的代码来支持数据库层,例如事务或持久性。 (具体而言,它们不需要继承自 EntityObject 类。) 仍可以使用数据注释来控制 Entity Framework 如何创建数据库架构。
由于 POCO 不携带描述 数据库状态的任何额外属性,因此可以轻松地将其序列化为 JSON 或 XML。 但是,这并不意味着应始终将实体框架模型直接公开给客户端,我们将在本教程的后面部分看到。
我们将创建以下 POCO:
- 产品
- 订单
- OrderDetail
若要创建每个类,请右键单击 解决方案资源管理器 中的 Models 文件夹。 在上下文菜单中选择“ 添加 ”,然后选择“ 类”。
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; }
}
}
按照约定,实体框架使用 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
的属性。 实体框架将推断这些属性表示外键,并将外键约束添加到数据库。
Order
和 OrderDetail
类还包括“导航”属性,这些属性包含对相关对象的引用。 给定订单后,可以按照导航属性导航到订单中的产品。
立即编译项目。 实体框架使用反射来发现模型的属性,因此它需要一个已编译的程序集来创建数据库架构。
配置Media-Type格式化程序
媒体类型格式化程序是在 Web API 写入 HTTP 响应正文时序列化数据的对象。 内置格式化程序支持 JSON 和 XML 输出。 默认情况下,这两个格式化程序都按值序列化所有对象。
如果对象图包含循环引用,则按值序列化会产生问题。 和 OrderDetail
类就是这种情况Order
,因为每个类都有对另一个类的引用。 格式化程序将遵循引用,按值写入每个对象,然后进入圆圈。 因此,我们需要更改默认行为。
在 解决方案资源管理器 中,展开 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。有关详细信息,请参阅 处理循环对象引用。)