Поделиться через


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

Рик Андерсон

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

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

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

  • Database-first: вы начинаете с базы данных, и Entity Framework создает код.
  • Model-first: вы начинаете с визуальной модели, и Entity Framework создает базу данных и код.
  • Code-first: вы начинаете с кода, и Entity Framework создает базу данных.

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

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

Мы создадим следующие объекты POCOS:

  • Продукт
  • Заказ
  • OrderDetail

Чтобы создать каждый класс, щелкните правой кнопкой мыши папку Models в Обозреватель решений. В контекстном меню выберите Добавить , а затем — Класс.

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

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