Що значить ім'я 3 база даних для spa або code first на entityframework

У попередній статті з циклу "Що значить ім'я" було показано що з себе представляє DurandalJS і як з ним працювати. У цій статті будемо працювати з EntityFramework: створимо базу даних за принципом Code First; створимо класи сутностей, налаштуємо SQL-підключення.

Приступаючи до роботи

Перед тим як почати використовувати BreezeJS слід підготувати базу даних. Саме цим ми і займемося в цій статті. Але для початку має сенс показати яка база даних "завалялася" у мене в папці під назвою "Може стати в нагоді", щоб ви могли чітко уявляти про що йде мова.

Схема бази даних

У мене давно "припадала пилом" база даних з тлумаченням імен. Вона настільки проста, що я приведу схему:

Що значить ім'я 3 база даних для spa або code first на entityframework

База даних у мене є, але використовувати її за прямим призначенням я не буду. Ми створимо нову базу даних за принципом "Code First", тобто ми створимо класи, а базу даних за нас створить EntityFramework. Після цього я перенесу з моєї архівної бази в нову базу тільки дані.

Хочу підкреслити, що наведена на зображенні БД - всього лише тільки для прикладу. Ми будемо створювати нову базу. А з цієї я тільки скопіюють дані, але не структуру.

Створюємо БД за принципом "Code First"

Для початку нам потрібні класи, тому що "Code" означає не що інше як "код", а значить класи. Я вже давно прийшов до того, що все повинно бути на своєму місці, ось і цього разу не можу вчинити інакше. Я звик розміщувати класи моделей в окремому проекті одного рішення (solution).

Що значить ім'я 3 база даних для spa або code first на entityframework

Створюємо новий проект:

Що значить ім'я 3 база даних для spa або code first на entityframework

Моделі для Code First

А тепер створюємо перший клас під назвою LetterInfo ... Хоча ні, давайте познайомимося з деякими принципами ООП, і зокрема, один з основоположних - "Спадкування". Створимо клас, який буде базовим для двох наступних. Клас назвемо ModelBase:

Зробили ми це тому, що кожен з двох наступних класів: LetterInfo і NameInfo міститимуть такі ж властивості:

У класі NameInfo не вистачає ще одного властивості (виходячи зі схеми зразковою бази даних), якого немає в базовому класі, додамо його:

Ось і готова архітектурна модель додатки.

Атрибути, класи, властивості, моделі

Вірніше початок покладено, тепер треба застосувати кілька атрибутів до властивостей і класам, щоб вказати EntityFramework деякі параметри при генерації таблиць бази даних. Для початку в базовому класі:

Атрибут Key вкаже EntityFramework, що дане поле є PrimaryKey (первинним ключем) для класів (таблиць), які будуть використовувати базовий клас як спадкоємця.

Взагалі, варто зробити пояснення. Насправді EntityFramework дуже "розумний" фреймворк. Якщо ви не встановите атрибут Key у цієї властивості, то EntityFramework все одно відзначити це поле як PrimaryKey. тобто зробить первинним ключем. Платформа EntityFramework покладається на те, що кожна сутність має значення ключа, яке використовується для відстеження сутностей. Одна з угод, на яку покладається Code First. полягає в тому, яким чином визначається ключове властивість в кожному класі Code First. Ця угода виконує пошук властивості Id або властивості, яке об'єднує "ім'я класу" і Id. наприклад LetterId. Властивість зіставляється зі стовпцем первинного ключа в базі даних.

У нашому випадку властивість Id буде в кожному з класів спадкоємців. Я все одно завжди ставлю цей атрибут, частіше за звичкою. Наступним по лістингу йде атрибут Display. Цей атрибут не стільки для EntityFramework, скільки для форм ASP.NET MVC і для читання коду в подальшому. Використання в розмітці Razor:

Форма відобразить значення властивості саме з атрибуту DisplayAttribute. Я також ставлю його практично завжди за звичкою, тому що в ньому можна вказати іменування поля по-російськи, хоча в нашому додатку цей атрибут марний, тому що рендеринг форми виробляє не Razor. а DurandalJS засобами KnockoutJS.

Наступне властивість - "Name". Але в нашому випадку, це властивість використовує різні настройки атрибутів для кожного із спадкоємців. Наприклад, в класі LetterInfo ця властивість має назву (DisplayAttribute) "Буква", в класі NameInfo - "Ім'я".

Створимо клас метаданих прямо в класах спадкоємців і перевизначити метадані базового класу в них. Спочатку розберемося з класом LetterInfo:

Для початку подивіться на рядок 4, де визначається клас метаданих LetterInfoMetadata. Зверніть увагу, що назва властивостей збігається з назвою властивостей в базовому класі ModelBase. Атрибут Display ми вже описали, наступний - Required (рядок 10). Цей атрибут вказує EntityFramework помітити властивість як обов'язкове, тобто запис в таблицю не потрапить поки не будуть заповнені всі обов'язкові поля. Далі атрибут StringLength (рядок 11), який встановлює обмеження на довжину рядка в таблиці SQL. Для властивості Content налаштуємо свої атрибути.

Наступний клас NameInfo:

Ліричний відступ: ви можете заперечити, до чого така складність при формуванні сутностей. Не буду заперечувати, це не найпростіший спосіб реалізації. Як альтернативне рішення, набагато простіше було б створити два класи, і в кожному реалізувати свої власні властивості з різними атрибутами. Тези на захист виконаної роботи:

  • Використання принципів і правил ООП (об'єктно-орієнтованого програмування) хороший тон для будь-якого програміста;
  • При подальшому розвитку проекту зміна базових властивостей можна здійснювати централізовано;
  • У будь-якому випадку, програмувати треба правильно і розвивати правильні звички.

Ще один тип атрибутів, який застосовується не до властивостей, а до класів. Одним з представників таких атрибутів є атрибут TableAttribute. Установка цього атрибуту на клас суті, дає можливість вказати EntityFramework назву для таблиці для цього класу.

Наприклад, для класу LetterInfo я встановив такий атрибут:

І, отже, таблиця, яку створить для мене EntityFramework, в якій будуть зберігатися назви букв, носитиме назву "Letters". а не "LetterInfo", якби я не поставив цей атрибут.

Проробимо те ж саме для другої сутності:

З такими атрибутами EntityFramework створить для мене дві таблиці з іменами Letters і Names. Прийшов час познайомитися з EntityFramework ближче.

DbContext або знайомство з EntityFramework

Що значить ім'я 3 база даних для spa або code first на entityframework

Насамперед треба встановити nuget-пакет, який дозволить розпочати роботу з EntityFramework. Виберіть проект InfoNames.Data правою кнопкою виберіть пункт Manage Nuget Packages. У менеджері пакетів виберіть зліва сховище "Microsoft and NET", EntityFramework-пакет буде на першому місці (в силу частоти завантажень), якщо його немає на першому місці, введіть EntityFramework в пошуку над колонкою інформації праворуч.

Що значить ім'я 3 база даних для spa або code first на entityframework

Натисніть кнопу Install.

Наступним етапом треба додати посилання на проект InfoNames.Models. Виберіть знову проект InfoNames.Data правою кнопкою викличте меню і знайдіть пункт Add -> Refferences:

Що значить ім'я 3 база даних для spa або code first на entityframework

Відзначте проект галкою і натисніть Ok. Добре. Тепер готово все, щоб почати створювати контекст БД, для цього створюємо новий клас ApplicationDbContext в проекті InfoNames.Data:

У конструкторі базового класу ми вказали назву рядка підключення "DefaultConnection". Давайте тепер рядок підключення до SQL server додамо в web.config проекту InfoNames.Web.

Зверніть увагу на параметр "Initial Catalog", він вказує назву для бази даних, яка буде створена в SQL сервері. У моєму випадку буде створена база "infonamesdb". Тепер в проект InfoNames.Web треба додати посилання на проект InfoNames.Data:

Що значить ім'я 3 база даних для spa або code first на entityframework

Виберіть проект, зазначивши його галкою і натисніть Ok. Добре, поїхали далі.

Команда Enable-Migrations

Давайте знову повернемося до проекту InfoNames.Data. треба включити міграції (migrations). Міграції для бази даних дозволять вносити зміни в структуру моделі даних програми "автоматично" при виклику команди Update-Database. Іншими словами, якщо ви щось упустили при розробки моделі, наприклад, забули який-небудь атрибут або пропустили якесь властивість, то при додаванні його в модель, потрібно виконати команду Update-Database щоб поновлення "прийшли" на SQL server. EntityFramework виконає основну роботу за вас, якщо будуть включені міграції, в іншому випадку, доведеться повністю видаляти базу і генерувати її заново. А якщо у вас вже є дані.

Увага: Не всі команди по зміні схеми бази даних можуть автоматично застосувати отримані зміни, деякі зміни доведеться обробляти "вручну" написавши команди (migrations) власноруч. Але швидше за все, особливо в простих структурах БД за вас все зробить автоміграціі.

У Package Manager Console виконайте команду:

У проекті InfoNames.Data з'явилася папка Migrations з файлом Configuration .cs

Міграції ми підключили, тепер давайте налаштуємо їх роботу на "автомат", для цього встановіть властивості в рядку 9 значення true і додайте ще одне:

Ось тепер остаточно встановлення всього цього. Можна перейти в Package Manager Console і виконати команду Update-Database:

Ура! виконано без помилок. У рядку 3 вказується, що явних міграцій, не знайдено (ті що пишуться "вручну"), а рядку 4 виявлені поновлення в структуру даних (природно, вона ж тільки що створена) і автоміграція пріменена.В рядку 5 повідомляється, що запущено метод Seed. Результатом виконання команди з'явилася нова база даних в списку SQL-сервера:

Що значить ім'я 3 база даних для spa або code first на entityframework

Якщо розгорнути і подивитися структуру таблиць:

Що значить ім'я 3 база даних для spa або code first на entityframework

Те, що і було потрібно отримати за результатами статті. Далі я експортує дані з моєї старої бази даних в нову (це залишиться "за кадром"). А в наступній статті почнемо роботу з BreezeJS.

висновок

В якості висновку хотілося б нагадати, що можна експериментувати, скачавши поточну версію проекту з Github.