Skip to content

Магазин на Asp.Net Core MVC EF. Частина 4

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Завантаження...

[ Полезный рекламный блок ]

Попробуйте свои силы в игре, где ваши навыки программирования на C# станут решающим фактором. Переходите по ссылке 🔰.


У цій статті, ми продовжимо писати магазин на Asp.Net Core і Entity Framework Core. У третій частині ми розширили магазин за рахунок додавання нових класів і створення відносин між ними. Дізналися, як запитувати пов’язані дані, яким чином виконувати оновлення. Для ознайомлення з третьою частиною, перейдіть за посиланням.

При створенні застосунку основна увага зазвичай приділяється побудові правильного фундаменту, і якраз такий підхід був прийнятий у проєкті GameStore. У міру розвитку програми часто корисно збільшувати обсяг даних, з якими проводиться робота, щоб можна було бачити, який вплив вони чинять на операції, що ініціюються користувачем, і на час, що потрібен для їх виконання. У цьому розділі до БД буде додано тестові дані, щоб продемонструвати недоліки способу, яким застосунок подає дані користувачеві, та вжити відповідних заходів за рахунок додавання підтримки розбиття на сторінки, упорядкування та пошуку в даних. Також буде показано, яким чином поліпшити продуктивність операцій з використанням інфраструктури Entity Framework Core, яка підтримує розширені варіанти конфігурації моделі даних, відомі як інтерфейс Fluent АРI.

Магазин на Asp.Net Core MVC EF. Частина 4

 

Створення контролера і подання для початкового заповнення даними

Нам необхідний контролер, який зможе заповнювати БД тестовими даними. Додайте в папку Controller, новий контролер SeedController, з таким вмістом:

Коли справа доходить до генерації великих обсягів тестових даних, то створення об’єктів .NET і їхнє збереження в БД буде неефективним. Контролер Seed застосовує засоби Entity Framework Core для роботи безпосередньо з SQL. щоб створити і виконати збережену процедуру, яка виробляє тестові дані набагато швидше.


Не робіть так у реальних проєктах

Цей підхід має використовуватися тільки для генерації тестових даних і ні в якій іншій частині програми. У цьому розділі потрібен механізм, який дає змогу надійно генерувати великі обсяги тестових даних, не вимагаючи виконання складних завдань у БД або застосування сторонніх інструментів.

Під час роботи безпосередньо з SQL слід дотримуватися обережності, оскільки в такому разі обходяться численні корисні засоби захисту, що забезпечуються інфраструктурою Entity Framework Core. Підсумковий код SQL важко тестувати і супроводжувати, до того ж часто виявляється, що він працює на єдиному сервері баз даних. Коротше кажучи, не використовуйте жодні аспекти продемонстрованого прийому у виробничих частинах своїх додатків.


Щоб забезпечити контролер поданням, створіть папку Views / Seed і помістіть у неї файл на ім’я Index.cshtml, з таким вмістом:

Подання дає змогу вказувати, скільки тестових даних має бути згенеровано, і відображає перші 20 об’єктів Product, які надаються запитом у дії Index контролера Seed. Щоб полегшити роботу з контролером Seed, додамо посилання в меню _Layout.cshtml:

Запустіть застосунок, перейдіть на сторінку Seed/Index.cshtml, виконайте очищення бази (якщо хочете), натиснувши кнопку “Очистити базу”. Тепер вкажіть значення 500 в елементі input і натисніть кнопку “Заповнити базу”. Генерація даних займе якийсь час, після чого ви побачите результат:

asp.net core shop talbe

Масштабування подання даних

Щоб продемонструвати вади способу, яким додаток GameStore представляє свої дані, особливо багато даних не потрібно. За наявності тисячі об’єктів метод подання даних користувачеві стає непридатним, і це все ще відносно невеликий обсяг даних, з яким додатку доводиться мати справу. У наступних розділах спосіб подання даних додатком GameStore буде змінено, щоб допомогти користувачеві виконувати основні операції та знаходити об’єкти, які його цікавлять.

Додавання підтримки розбиття на сторінки

Першим буде розв’язано задачу розбиття даних, що подаються користувачеві, для того, щоб вони не виглядали як один довгий список. Використання простих таблиць, які включають всі об’єкти, є зручним підходом, коли формуються основи додатка, але таблиці, що містять тисячі рядків, непридатні для застосування в більшості додатків. Щоб розв’язати цю проблему, ми додамо підтримку запитування в БД невеликих обсягів даних і дозволимо користувачеві переміщатися, перегортаючи такі сторінки з невеликими обсягами даних.

Під час роботи з великими обсягами даних важливо забезпечити узгоджене управління доступом до цих даних, щоб в однієї частини застосунку не було жодної можливості випадково запросити мільйони об’єктів. Ми приймемо підхід, що передбачає створення класу колекції, який містить у собі розбиття на сторінки.

Для визначення колекції, яка забезпечить доступ до розбитих на сторінки даних, створимо папку Models/Pages, додамо до неї файл клас на ім’я PagedList.cs, з таким вмістом:

Як базовий клас використовується строго типізований List. який дозволить легко нарощувати базову поведінку колекції. Конструктор приймає об’єкт реалізації IQueryable<T>, що представляє запит, який буде постачати дані для відображення користувачеві. Такий запит буде виконуватися двічі – один раз для отримання загальної кількості об’єктів, яку міг би повернути запит, і один раз для отримання тільки об’єктів, що підлягають відображенню на поточній сторінці. Це компроміс, притаманний розбиттю на сторінки, за якого додатковий запит COUNT врівноважується запитами для меншої кількості об’єктів загалом. В інших аргументах конструктора вказуються сторінка, необхідна для запиту, і кількість об’єктів, що відображаються на сторінці.

Для представлення параметрів, необхідних запиту, додайте в папку Models/Pages файл класу на ім’я QueryOptions.cs з таким вмістом:

Оновлення сховища

Щоб забезпечити узгоджене застосування засобу розбивки на сторінки, як результат виконуваних у сховищі запитів буде повертатися об’єкт PagedList. Додайте в інтерфейс IProduct, метод на ім’я GetProduct(), який повертає дані для одиночної сторінки:

Новий метод повертає колекцію PagedList об’єктів Product для сторінки, зазначеної аргументами.

Оновлення контролера та подання

Для додавання в контролер Home підтримки розбивки на сторінки змініть, дію Index, щоб вона приймала аргументи, необхідні при виборі сторінки, і в результаті використовувала новий метод сховища:

Базовий клас колекції даних, розбитих на сторінки, реалізує інтерфейс IEnumerable<T>, який зводить до мінімуму обсяг змін, необхідних для підтримки розбитих на сторінки даних. Єдина зміна, яку знадобиться внести в подання для дії Index контролера Home, пов’язана з відображенням часткового подання з деталями розбиття на сторінки.

Щоб завершити підтримку розбиття на сторінки для об’єктів Product, визначте часткове подання, додавши в папку Views / Shared файл на ім’я Pages.cshtml із таким вмістом:

Представление содержит НТМL-форму, которая применяется для отправки НТТР­

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

Так само обов’язково додайте до <form>, id=”pageform”, він нам стане в нагоді в наступному частковому поданні.

Під час запуску програми список товарів буде розбито на 10 елементів, за якими можна переходити за допомогою послідовності кнопок:

asp.net core orderby

Виконайте переходи посторінково, змініть кількість сторінок для відображення, перевірте роботу програми.

Додавання підтримки пошуку та впорядкування

Відображення сторінок – гарний початок, але концентруватися на специфічному наборі об’єктів, як і раніше, важко. Для оснащення користувача інструментами знаходження даних, які його цікавлять, ми додамо до розбивки на сторінки підтримку зміни порядку відображення і виконання пошуку. Відправною точкою буде розширення класу PagedList, щоб він міг виконувати пошук і впорядковувати результати запитів із використанням імен властивостей, а не лямбда-виразів, що вибирають властивості.

Виконання таких операцій потребуватиме дещо заплутаного коду, але результат може бути застосований до будь-якого класу моделі даних і легше інтегрується з частинами ASP.NET Сore MVC додатка.

Змінимо визначення класу PagedList таким чином:

Перейдемо в клас QueryOptions, і змінимо його вміст таким чином:

Щоб створити узагальнене подання, яке пропонуватиме користувачеві можливості пошуку та впорядкування, додамо в папку Views/Shared файл на ім’я PageOptions.cshtml, з таким вмістом:

Подання спирається на можливість HTML 5 асоціювати з формами елементи, визначені за межами елемента form. Це дає змогу розширити форму, яка визначена в поданні Pages, елементами, специфічними для пошуку та впорядкування.

Жорстко кодувати список властивостей, які користувач може задіяти для пошуку або впорядкування даних у поданні, небажано, тому з метою простоти такі значення отримують із ViewBag. Рішення не вважається ідеальним, але воно забезпечує високу гнучкість і дає змогу легко адаптувати один і той самий вміст до різних подань і даних.

Щоб відобразити користувачеві елементи, пов’язані з пошуком і впорядкуванням, поряд зі списком об’єктів Product, додамо до подання Index, яке використовується контролером Ноmе, такий вміст:

Блок коду вказує властивості класу Product, за допомогою яких користувач отримає можливість шукати й упорядковувати об’єкти Product, а вираз @Html.Partial візуалізує елементи для таких засобів.

Применение возможностей представления данных к категориям

Процес розміщення засобів для розбиття на сторінки, пошуку та сортування на своїх місцях був непростим, але тепер, коли фундамент готовий, їх можна застосувати до інших типів даних у застосунку, як-от об’єкти Category.

Насамперед оновимо інтерфейс ICategory і класи реалізації, додавши метод, який приймає об’єкт QueryOptions і повертає результат PagedList:

Тепер сам клас CategoryRepository:

Додамо параметр QueryOptions до дії Index контролера CategoriesController, який керує об’єктами Category, і використаємо його для запитування сховища:

Нарешті, надамо користувачеві можливість роботи із засобами, додавши елементи в подання Index, яке застосовується контролером CategoriesController:

Запустіть додаток, перейдіть на сторінку Категорій. На сторінці присутній список категорій, а користувач може виконувати в них пошук і впорядкування. Перевірте все самі:

asp.net core pagination

Индексация базы данных

Додавання в БД тисячі тестових об’єктів виявилося достатнім для демонстрації обмежень способу, яким дані представлялися користувачеві, але такого обсягу даних не вистачить, щоб виявити обмеження самої БД. Для з’ясування ефекту від роботи з великими обсягами даних додамо до конструктора PagedList оператори, які вимірюють тривалість виконання запиту і виводять витрачений час на консоль. Перейдемо в клас PagedList і доповнимо конструктор таким кодом:

Запустіть додаток, перейдіть на сторінку “Початкові дані” і заповніть БД потрібною кількістю об’єктів. Після цього, перейдіть на сторінку товарів, виберіть властивість PurchasePrice для сортування і виконайте його.

Якщо ви переглянете журнальні повідомлення, згенеровані додатком, то помітите запити, що застосовувалися для отримання даних, а також час їхнього виконання:

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

Кількість об’єктів Час
1000 86 мс
10 000 104 мс
100 000 314 мс
1 000 000 2578 мс
2 000 000 5156 мс

Створення та застосування індексів

Одна з проблем із продуктивністю виникає через те, що серверу баз даних доводиться досліджувати багато рядків даних у пошуку даних, необхідних додатку. Ефективний спосіб скорочення обсягу роботи, виконуваної сервером баз даних, передбачає створення індексів, які прискорюють запити, але потребують певного часу на початкову підготовку та невеликої додаткової роботи після кожного оновлення. Що стосується додатка GameStore, то ми додамо індекси для властивостей класів Product і Category, які користувач зможе використовувати під час пошуку або впорядкування даних.

Створимо індекси в класі ApplicationContext контексту БД, для цього додамо метод OnModelCreating як показано в наступному коді:

Метод OnModelCreating() перевизначений для налаштування моделі даних із застосуванням засобу Fluent API з Entity Framework Core. Інтерфейс Fluent API дає змогу перевизначати стандартні лінії поведінки Entity Framework Core і отримувати доступ до розширених можливостей, таких як створення індексів. У цьому випадку створюються індекси для властивостей Name, PurchasePrice і RetailPrice класу Product, а також для властивостей Name і Description класу Category.

Створювати індекси для властивостей первинних або зовнішніх ключів не потрібно, оскільки інфраструктура Еntity Framework Core за замовчуванням створює їх самостійно.

Створення індексів вимагає створення нової міграції та її застосування до БД.

Для створення міграції у вікні Package Manager Console введіть таку команду:

asp.net core add migration

Для виконання інструкцій міграції, у вікні Package Manager Console виконайте команду:

Інфраструктура Entity Fгamework Core підключиться до сервера баз даних, зазначеного в рядку підключення, і виконає оператори в міграції

P.S. За наявності в БД великого обсягу даних застосування міграції, що створює індекси, може зайняти деякий час, тому що всі наявні дані мають бути додані в індекс. Перед виконанням команд міграції, можливо, у вас виникне бажання скористатися контролером Seed для скорочення обсягу тестових даних.

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

Кількість об’єктів Час
1000 48 мс
10 000 61 мс
100 000 104 мс
1 000 000 287 мс
2 000 000 301 мс

Підсумок

У статті було показано, яким чином адаптувати додаток GameStore для роботи з більшими обсягами даних. Ми додали до нього підтримку розбиття на сторінки, упорядкування та пошуку даних, що дає змогу користувачеві мати справу з керованою кількістю об’єктів за раз. Крім того, за допомогою Fluent АРI було налаштовано модель даних і додано індекси для поліпшення продуктивності запитів. У наступному розділі до додатка GameStore буде додано інтерфейс для покупців.

На цьому стаття “Магазин на Asp.Net Core MVC EF”, підійшла до кінця, сподіваюся вам було цікаво. Ви можете завантажити вихідний код у моєму репозиторії — Github.

Поділіться вашим досвідом у коментарях, який був ваш перший проєкт, магазин на Asp.Net Core MVC EF або щось інше?

Так само вам може бути цікава попередня стаття:

Оптимізація зображень для сайту на C#


Ви хочете навчитися писати код мовою програмування C#?

Створювати різні інформаційні системи, що складаються з сайтів, мобільних клієнтів, десктопних додатків, телеграм-ботів тощо.

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

  • Доступ до пройденого матеріалу
  • Тематичні статті
  • Бібліотека книг
  • Онлайн тестування
  • Спілкування в закритих групах

https://dijix.com.ua

Живи у своєму світі, програмуй у нашому.


 

Published inAsp.Net Core
Subscribe
Notify of
guest
2 комментариев
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Алексей
Алексей
6 months ago

Отличная вышла статья. Я с Удовольствием сначало прочитал, а после решил воплотить своими ручками. Да, столкнулся с некоторыми ошибками, не без этого. А в целом Спасибо Вам, за такую проделанную работу.

Володя
Володя
6 months ago

Дуже дякую!

2
0
Would love your thoughts, please comment.x
()
x