Перейти к содержанию

Магазин на 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 Соге 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 позволяет переопределять стандартные линии поведения Eпtity Framework Core и получать доступ к расширенным возможностям, таким как создание индексов. В данном случае создаются индексы для свойств Name, PurchasePrice и RetailPrice класса Product, а также для свойств Name и Description класса Category.

Создавать индексы для свойств первичных или внешних ключей не нужно, поскольку инфраструктура Eпtity 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 или что-то другое?

Так же вам может быть интересна предыдущая статья:

Как опубликовать приложение Asp.Net Core


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

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

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

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

https://dijix.com.ua

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


 

Опубликовано в рубрикеAsp.Net Core
Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x