Часть 2. Создание моделей домена

Рик Андерсон

Скачивание завершенного проекта

Добавление моделей

Существует три способа подхода к Entity Framework:

  • База данных— сначала вы начинаете с базы данных, а Entity Framework создает код.
  • Сначала модель: вы начинаете с визуальной модели, а Entity Framework создает базу данных и код.
  • Подход Code First: Вы начинаете с кода, и Entity Framework генерирует базу данных.

Мы используем подход от кода, поэтому начинаем с определения объектов нашей предметной области как POCO (простые объекты CLR). При первом подходе к коду объекты домена не нуждаются в дополнительном коде для поддержки уровня базы данных, например транзакций или сохраняемости. (В частности, они не должны наследоваться от класса EntityObject .) Заметки данных по-прежнему можно использовать для управления тем, как Entity Framework создает схему базы данных.

Так как POC не несут никаких дополнительных свойств, описывающих состояние базы данных, их можно легко сериализовать в JSON или XML. Однако это не означает, что вы всегда должны предоставлять модели Entity Framework непосредственно клиентам, как мы увидим далее в этом руководстве.

Мы создадим следующие POCOs:

  • Товар
  • Заказ
  • Детали Заказа

Чтобы создать каждый класс, щелкните правой кнопкой мыши папку 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 свойство при создании формы редактора. Обязательный атрибут используется для проверки модели. Он указывает, что 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 будет выводить, что эти свойства представляют внешние ключи и будут добавлять ограничения внешнего ключа в базу данных.

Снимок экрана: меню Visual Studio для классов Orders, Products и OrderDetails.

Классы Order и OrderDetail также включают свойства "навигации", которые содержат ссылки на связанные объекты. Получив заказ, вы можете перейти к продуктам в рамках этого заказа, используя навигационные свойства.

Скомпилируйте проект. Entity Framework использует отражение для обнаружения свойств моделей, поэтому для создания схемы базы данных требуется скомпилированная сборка.

Настройка модулей форматирования Media-Type

Средство форматирования типа мультимедиа — это объект, который сериализует данные, когда веб-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 для этого приложения. Дополнительные сведения см. в разделе "Обработка циклических ссылок на объекты".)