作者:里克·安德森
添加模型
可通过三种方法接近 Entity Framework:
- 数据库优先:从数据库开始,Entity Framework 将生成代码。
- 模型优先:从视觉对象模型开始,实体框架将生成数据库和代码。
- 代码优先:从代码开始,Entity Framework 将生成数据库。
我们使用的是代码优先方法,因此首先将域对象定义为 POCO(普通旧 CLR 对象)。 使用代码优先方法时,域对象不需要任何额外的代码来支持数据库层,例如事务或持久性。 (具体而言,它们不需要继承自 EntityObject 类。你仍然可以使用数据注释来控制 Entity Framework 如何创建数据库架构。
由于 POCO 不携带任何描述 数据库状态的额外属性,因此可以轻松序列化为 JSON 或 XML。 但是,这并不意味着应始终将实体框架模型直接公开给客户端,因为我们将在本教程的后面部分看到。
我们将创建以下 POCO:
- 产品
- 下单
- 订单详情
若要创建每个类,请右键单击解决方案资源管理器中的 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; }
}
}
按照约定,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 类还包括“导航”属性,这些属性包含对相关对象的引用。 在接收到订单后,可以按照导航属性定位到订单中的产品。
立即编译项目。 实体框架使用反射来发现模型的属性,因此需要编译的程序集来创建数据库架构。
配置媒体类型格式化程序
在 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。有关详细信息,请参阅 处理循环对象引用。)