Parte 2: Criando os modelos de domínio
por Rick Anderson
Adicionar modelos
Há três maneiras de abordar o Entity Framework:
- Primeiro banco de dados: você começa com um banco de dados e o Entity Framework gera o código.
- Model-first: você começa com um modelo visual e o Entity Framework gera o banco de dados e o código.
- Code-first: você começa com o código e o Entity Framework gera o banco de dados.
Estamos usando a abordagem code-first, portanto, começamos definindo nossos objetos de domínio como POCOs (objetos CLR simples). Com a abordagem code-first, os objetos de domínio não precisam de nenhum código extra para dar suporte à camada de banco de dados, como transações ou persistência. (Especificamente, eles não precisam herdar da classe EntityObject .) Você ainda pode usar anotações de dados para controlar como o Entity Framework cria o esquema de banco de dados.
Como os POCOs não carregam nenhuma propriedade extra que descreva o estado do banco de dados, eles podem ser facilmente serializados para JSON ou XML. No entanto, isso não significa que você sempre deve expor seus modelos do Entity Framework diretamente aos clientes, como veremos posteriormente no tutorial.
Criaremos os seguintes POCOs:
- Produto
- Ordem
- OrderDetail
Para criar cada classe, clique com o botão direito do mouse na pasta Modelos no Gerenciador de Soluções. No menu de contexto, selecione Adicionar e, em seguida, selecione Classe.
Adicione uma Product
classe com a seguinte implementação:
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; }
}
}
Por convenção, o Entity Framework usa a Id
propriedade como a chave primária e a mapeia para uma coluna de identidade na tabela de banco de dados. Ao criar uma nova Product
instância, você não definirá um valor para Id
, porque o banco de dados gera o valor.
O atributo ScaffoldColumn informa ASP.NET MVC para ignorar a Id
propriedade ao gerar um formulário de editor. O atributo Obrigatório é usado para validar o modelo. Ele especifica que a Name
propriedade deve ser uma cadeia de caracteres não vazia.
Adicione a Order
classe :
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; }
}
}
Adicione a OrderDetail
classe :
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; }
}
}
Relações de Chave Externa
Um pedido contém muitos detalhes do pedido e cada detalhe do pedido refere-se a um único produto. Para representar essas relações, a OrderDetail
classe define as propriedades denominadas OrderId
e ProductId
. O Entity Framework inferirá que essas propriedades representam chaves estrangeiras e adicionará restrições de chave estrangeira ao banco de dados.
As Order
classes e OrderDetail
também incluem propriedades de "navegação", que contêm referências aos objetos relacionados. Dado um pedido, você pode navegar até os produtos na ordem seguindo as propriedades de navegação.
Compile o projeto agora. O Entity Framework usa reflexão para descobrir as propriedades dos modelos, portanto, requer um assembly compilado para criar o esquema de banco de dados.
Configurar os formatadores de Media-Type
Um formatador de tipo de mídia é um objeto que serializa seus dados quando a API Web grava o corpo da resposta HTTP. Os formatadores internos dão suporte à saída JSON e XML. Por padrão, ambos os formatadores serializam todos os objetos por valor.
A serialização por valor criará um problema se um grafo de objeto contiver referências circulares. Esse é exatamente o caso com as Order
classes e OrderDetail
, porque cada uma tem uma referência à outra. O formatador seguirá as referências, gravando cada objeto por valor e entrará em círculos. Portanto, precisamos alterar o comportamento padrão.
Em Gerenciador de Soluções, expanda a pasta App_Start e abra o arquivo chamado WebApiConfig.cs. Adicione o código a seguir à classe 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);
}
}
Esse código define o formatador JSON para preservar referências de objeto e remove totalmente o formatador XML do pipeline. (Você pode configurar o formatador XML para preservar referências de objeto, mas é um pouco mais de trabalho e só precisamos de JSON para este aplicativo. Para obter mais informações, consulte Manipulando referências de objeto circular.)