Предыдущий ролик Следующий ролик  

Видео урок: Generating database objects with the Entity Framework

Основы ASP.NET MVC 5

На примере модели CheckingAccountModel, созданной в начале первой главы, мы рассмотрим процесс написания небольшого фрагмента кода, который связывает аккаунт пользователя с текущим счетом, а затем автоматически генерирует таблицы базы данных, отражающие это взаимодействие. Если вы еще не сталкивались с Entity Framework и с объектно-реляционным отображением, или ORM, в целом, то можете ознакомиться с третьей главой моего курса "Работа с ASP.NET", которая предоставит вам вводную информацию. В классе AccountController мы видели, что новый счет создается в методе Register с помощью экземпляра ApplicationUser.

Если нажать правую кнопку мыши и выбрать пункт "Перейти к определению", то можно увидеть, что этот класс определяется в файле IdentityModels.cs и наследуется от класса IdentityUser. IdentityUser - это модель, которая может храниться в базе данных и обладает такими свойствами, как Username и PasswordHash. Можно добавить еще дополнительные свойства, которые должны храниться в этом унаследованном классе. В этом файле есть еще определение ApplicationDbContext, унаследованного от класса IdentityDbContext, который в свою очередь унаследован от класса DbContext.

DbContext будет выступать в качестве слоя объектов, используемого для взаимодействия с базой данных. Поскольку мы выполняем наследование от класса IdentityDbContext, мы уже получаем такие свойства, как Users и Roles, которые можно использовать для работы непосредственно с данными о пользователе, полученными из нашей базы данных. Строка "DefaultConnection", передаваемая в конструктор базового класса, ссылается на строку подключения из файла Web.config, которая используется для подключения к базе данных или для создания базы данных, если таковая еще не существует.

В секции connectionstrings файла Web.config можно увидеть, что строка подключения ссылается на экземпляр LocalDb SQL-сервера. Маркер DataDirectory, заключенный в прямые слэши, олицетворяет собой папку App_Start нашего проекта, в которой будет создан файл базы данных на основании этого имени файла. Когда мы будем выполнять развертывание на реальном сервере, эти настройки можно будет легко изменить, для того чтобы использовать полную версию SQL-сервера. Можно даже задавать отдельные настройки для этапа разработки и реализации.

Вот теперь все на своих местах. Но в класс ApplicationDbContext нам хотелось бы добавить еще один член, который демонстрирует данные о текущем счете. Делается это путем добавления открытого свойства, которое будет относиться к видовому типу DbSet<CheckingAccount>. Назовем это свойство "CheckingAccounts". Нужно продемонстрировать также System.Data.Entity. Опять же, это позволит нам работать непосредственно с таблицей CheckingAccount, которая вскоре будет создана в базе данных. В класс CheckingAccount мы добавим еще одно свойство, представляющее собой ссылку на пользователя, владеющего данным счетом.

Это будет реализовано автоматически с помощью внешнего ключа, который ссылается на таблицу User при генерации базы данных. Благодаря тому, что мы сделали это свойство виртуальным, фреймворк может переопределить его с помощью механизма, поддерживающего отложенную загрузку (lazy loading) данного связанного объекта. Итак, мы действительно можем передать объект User в это свойство и сделать так, чтобы он обновлялся в базе данных, но для некоторых сценариев будет удобнее передавать ID пользователя. Поэтому мы добавляем следующее свойство, а Entity Framework, опять же, достаточно умен для того, чтобы понять, что мы говорим о свойстве ID соответствующей сущности.

Наконец, вернемся к методу Register. Если пользователь успешно создан, можно задать для него новый текущий счет. Объявляем новый экземпляр ApplicationDbContext и checkingAccount. Скопируем параметры FirstName и LastName из RegisterViewModel, используем для AccountNumber небольшую хитрость - жестко закодируем его. Параметр Balance для абсолютно нового счета должен иметь значение "0". А параметру ApplicationUserId присвоим значение user.Id только что созданного нового пользователя.

Затем нам нужно просто добавить этот checkingAccount в базу данных CheckingAccounts и вызвать метод SaveChanges. Нажмем клавишу Ctrl+F5, чтобы сохранить изменения и запустить приложение, а затем выполним регистрацию. Обратите внимание, что теперь я авторизовался в системе и могу найти только что созданную базу данных в папке App_Data, нажав кнопку "Показать все файлы" (Show all files).

Откройте ее двойным щелчком мыши в Обозревателе серверов. В папке Tables выберите файл AspNetUsers и в контекстном меню выберете пункт "Показать данные таблицы" (Show table data). Обратите внимание на ID вот здесь, а затем на такой же ID для ApplicationUserId в таблице CheckingAccounts. Если рассматривать таблицу в таком виде, то нельзя сказать, что ApplicationUserId - это внешний ключ. Но если выбрать пункт "Открыть определение таблицы" (Open table definition), то можно увидеть более полную информацию.

Итак, это своего рода ловкий трюк. Но теперь, когда мы сгенерировали из наших классов моделей реальную базу данных, вносить изменения в эти модели и выполнять синхронизацию будет немного сложнее. Мы обсудим это в следующем видео, посвященном функции Code-First Migrations.