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

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

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

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

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


В этой статье, мы продолжим писать магазин на Asp.Net Core и Entity Framework Core. В первой части мы добавили поддержку для сохранения данных в БД и выдачи запросов к ней. Для ознакомления с первой частью, перейдите по ссылке.

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

Модификация и удаление данных

Обновление контроллера и создание представления

Обновление только измененных свойств

Выполнение массовых обновлений

Изменение хранилища

Изменение представлений и контроллера

Использование средства обнаружения изменений в файле

Удаление данных

Итог

 

Модификация и удаление данных

В текущий момент приложение GameStore способно сохранять объекты Product в БД и выполнять запросы для их чтения обратно в память. Большинству приложений также требуется возможность вносить изменения в данные после того, как они были сохранены, включая полное удаление объектов. В этой главе будет добавлена поддержка для обновления и удаления объектов Product. Вдобавок обсуждаются проблемы, с которыми вполне вероятно вы столкнетесь при добавлении таких средств в собственные проекты, и объясняется, как их решить.

Инфраструктура Entity Framework Core поддерживает несколько способов обновления объектов. В текущей главе мы начнем с простейшего приема, при котором объект, созданный связывателем моделей MVC, применяется для полной замены объекта, хранящегося в БД.

Первым делом измените интерфейс IProduct, добавив к нему методы, которые можно использовать в остальном коде приложения для извлечения и обновления существующего объекта:

Метод GetProduct() предоставит одиночный объект Product по значению его первичного ключа. Метод UpdateProduct() получает объект Product и какого-либо результата не возвращает.

Реализуем данные методы, в классе репозитории ProductRepository:

Объект DbSet<Product>, возвращаемый свойством Products контекста БД, пре­доставляет функциональное средство, которое необходимо для реализации новых методов. Метод Find() принимает значение первичного ключа и запрашивает у БД соответствующий ему объект. Метод Update() принимает объект Product и применяет его для обновления БД, заменяя объект в БД с тем же самым первичным ключом. Как и в случае всех операций, которые изменяют БД, после вызова Update() понадобится вызвать метод SaveChanges().

Помнить о необходимости вызова метода SaveChanges() может показаться трудновыполнимой задачей, но это быстро войдет в привычку. Такой подход означает, что вы можете подготовить множество изменений, вызывая методы объекта контекста, и затем одновременно отправить их БД с помощью единственного вызова SaveChanges().

Обновление контроллера и создание представления

Следующий шаг заключается в обновлении контроллера Home, чтобы добавить методы действий, которые позволят пользователю выбрать объект Product для редактирования и отправить изменения приложению.

Добавим 2 новых действия в HomeController:

Вы можете заметить, как методы действий сопоставляются со средствами, предоставляемыми хранилищем, посредством класса контекста БД. Чтобы снабдить контроллер представлением для новых действий, добавьте в папку Views/Horne файл по имени UpdateProduct.cshtml, со следующим содержимым:

Представление UpdateProduct.cshtml снабжает пользователя НТМL-формой, которую можно использовать для изменения свойств объекта Product за исключением свойства Id, применяемого в качестве первичного ключа. Первичные ключи нелегко изменить после того, как они были назначены, и если требуется другое значение ключа, то проще удалить объект и создать новый. По этой причине к элементу input добавлен атрибут readonly, который позволяет видеть значение свойства Id, но не изменять его. Либо поле с Id, можно вообще скрыть с глаз пользователя.

Для интеграции средства обновления с остальным кодом приложения добавим элемент button к каждому объекту Product, отображаемому представлением Index.cshtml:

Запустите приложение, выберите любой товар и нажмите кнопку “Изменить”:

products asp.net core

Измените любое значение на выбранном товаре и нажмите кнопку “Сохранить”:

редактирование asp.net core

Если вы просмотрите журнальные сообщения, сгенерированные приложением, то сможете увидеть, как выполняемые действия превращаются в SQL-команды, отправляемые серверу баз данных. Когда вы щелкаете на кнопке Edit, инфраструктура EntityFramework Core запрашивает у БД детали выбранного объекта  с помощью следующей команды:

Метод Find(), транслируется в команду SELECT для одиночного объекта, который указан с использованием ключевого слова ТОР. После щелчка на кнопке Save инфраструктура Entity Framework Саге обновляет БД с помощью такой команды:

Метод Update() транслируется в SQL-команду UPDATE, которая сохраняет значе­ния данных формы, полученные из НТTР-запроса.

Обновление только измененных свойств

Основные строительные блоки для выполнения обновлений на месте, но результат неэффективен, поскольку инфраструктура Entity Framework Core не располагает исходными данными для оценки, что конкретно изменилось, и не имеет другого выбора, кроме сохранения всех свойств. Чтобы взглянуть на проблему, щелкните на кнопке Edit для одного из товаров и затем щелкните на кнопке Save, не внося каких-либо изменений. Хотя новые значения данных не вводились, журнальные сообщения, сгенерированные приложением, говорят о том, что выпущенная инфраструктурой EntityFramework Core команда UPDATE посылает значения для всех свойств, которые определены в классе Product:

Инфраструктура Entity Framework Core содержит средство обнаружения изменений, которое способно выявить, какие свойства были изменены. Для такого простого класса модели данных, каковым является Product, польза от этого средства невелика, но в случае более сложных моделей обнаружение изменений может быть важным.

Средство обнаружения изменений требует исходных данных, с которыми можно было бы сравнить данные, полученные от пользователя. Есть разные способы предоставления исходных данных (они описаны в главе 12), но здесь будет применен простейший подход, который предусматривает запрашивание у БД существующих данных.

Изменим метод UpdateProduct, класса ProductRepository, следующим образом:

Код объединяет в приложении две разных функции. Инфраструктура Entity Framework Core отслеживает изменения в объектах, которые создает из данных запросов, в то время как связыватель моделей MVC создает объекты из НТГР-данных. Упомянутые два источника объектов не объединены, и если не соблюдать осторожность при удержании их раздельными, то возникнут проблемы. Самый безопасный способ задействовать в своих интересах отслеживание изменений — запросить БД и затем скопировать значения из НТГР-данных, как было сделано.

Когда вызывается метод SaveChanges(), инфраструктура Entity Framework Core выяснит, значения каких свойств изменились, и обновит в БД только эти свойства.

Запустите приложение, выполните изменение закупочной стоимости любого продукта и просмотрите текущий запрос:

Выполнение массовых обновлений

Массовые обновления часто требуются в приложениях, где предусмотрены отдельные роли администраторов, которым необходимо вносить изменения во множество объектов в единственной операции. Точная природа обновлений будет варьироваться, но распространенные причины для массовых обновлений включают исправление ошибок в записях данных или переназначение объектов в новые категории, что может оказаться затратным по времени процессом в случае выполнения на индивидуальных объектах. С использованием инфраструктуры Entity Framework Core делать массовые обновления легко, но требуются небольшие усилия, чтобы обеспечить их гладкую работу с частью ASP.NEТ Core MVC приложения.

Изменение хранилища

Добавьте в интерфейс  хранилища IProduct новый метод, который будет выполнять массовое обновление:

Наконец, добавьте в репозиторий ProductRepository реализацию метода UpdateAll(), который будет обновлять БД с применением данных, полученных из НТТР-запроса:

Класс DbSet<T> предлагает методы для работы с индивидуальными объектами и с коллекциями объектов. В этом примере используется метод UpdateRange(), который является аналогом метода Update(), но работает с коллекциями. Когда вызывается метод SaveChanges(), инфраструктура Entity Framework Core отправляет последовательность SQL-команд UPDATE для обновления БД.

Изменение представлений и контроллера

Для добавления поддержки массовых обновлений измените, представление Index, включив в него кнопку Edit All (Редактировать все), которая нацелена на действие UpdateAll. Также добавьте свойство типа ViewBag по имени UpdateAll. Если его значением является true, тогда будет отображаться частичное представление InlineEditor.cshtml:

Создайте частичное представление, добавив в папку Views/Home файл по имени InlineEditor.cshtml, со следующим содержимым:

Частичное представление создает набор элементов формы, имена которых следу­ ют соглашению, принятому в МVС для коллекции объектов, а потому свойству Id назначаются имена Products[0].Id, Products[1].Id и т.д. Установка имен элементов input требует счетчика, что порождает неуклюжую смесь выражений Razor и С#.

Добавьте в контроллер Ноше методы действий, которые позволят пользователю начать процесс массового редактирования и отправить данные:

На данном этапе, структура проекта выглядит следующим образом:

структура проекта asp.net core

Запустите приложение и выполните массовое редактирование товаров:

asp.net core редактирование объектов

 

 

 

Использование средства обнаружения изменений в файле

В предыдущем коде не применяется средство обнаружения изменений Entity Framework Core, т.е. будут обновляться все свойства всех объектов Product. Чтобы обновлять только изменившиеся значения, изменит метод UpdateAll, в классе ProductRepository, следующим образом:

Процесс выполнения обновления может выглядеть запутанным. Сначала создается словарь объектов Product, полученных от связывателя моделей MVC, с применением свойства Id для ключей. Коллекция ключей используется для запрашивания соответствующих объектов в БД. Далее происходит перечисление объектов БД с копированием значений свойств из объектов НТТР-запроса. После вызова метода SaveChanges() инфраструктура EF выполняет обнаружение изменений и обновляет только те свойства, значения которых изменились.

Запустите приложение и выполните массовое редактирование товаров. Просмотрите журнальные сообщения, сгенерированные приложением. Сравните запросы с разными версиями метода UpdateAll.

Удаление данных

Удаление объектов из БД — процесс простой, хотя с разрастанием модели данных он может усложниться. В интерфейс IProduct, добавим следующий метод:

В классе ProductRepository, реализуем данный метод:

Класс DbSet<T> имеет методы Remove() и RemoveRange(), предназначенные для удаления одного и нескольких объектов из БД. Как и в случае других операций, модифицирующих БД, данные не удаляются до тех пор, пока не будет вызван метод SaveChanges().

Добавьте в контроллер Home метод действия, который получает из НТТР­ запроса детали подлежащего удалению объекта Product и передает их хранилищу:

В представление Index, добавим элемент form:

Обратите внимание, что форма содержит единственный элемент input для свойства Id. Это все, что инфраструктура Entity Framework Core применяет для удаления объекта из БД, хотя операция выполняется над полным объектом Product. Вместо отправки дополнительных данных, которые не планируется использовать, было послано только значение первичного ключа, которое связыватель моделей MVC применит для создания объекта Product, оставляя все другие свойства равными null или стандартному значению для типа.

Запустите приложение и выполните удаление любого продукта.

Итог

В главе к приложению GameStore была добавлена поддержка для обновления и удаления объектов. Вы узнали, каким образом модифицировать индивидуальные объекты и выполнять массовые обновления, а также как снабжать инфраструктуру Entity Framework Core исходными данными для ее средства обнаружения изменений. Кроме того, было показано, как удалять данные, что делается просто в случае модели данных с единственным классом и усложняется с разрастанием модели данных. В следующем уроке модель данных для приложения GameStore будет расширена.

На этом статья «Магазин на Asp.Net Core MVC EF 2», подошла к концу, надеюсь вам было интересно.  Вы можете скачать исходный код в моем репозитории — Github.

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

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

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


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

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

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

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

https://dijix.com.ua

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

 

Опубликовано в рубрикеAsp.Net Core
Подписаться
Уведомить о
guest
5 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Artem
Artem
1 год назад

В HomeController используется два раза UpdateProduct и они начинают конфликтовать, лучше второй метод переименовать во что-то по типу UpdateProductAction и соответственно к нему обращаться в html файле.
Плюсом, в интерфейсах не создается GetProduct, его надо самостоятельно прописать Product GetProduct(int id);
Ну и желательно везде сделать проверку на NULL, чтобы не было недоразумений потом у пользователей.

Artem
Artem
1 год назад
Ответить на  Леонид Каруна

Извиняюсь, я тогда не знал, что перед каждым методом надо ставить атрибут [HttpGet] или [HttpPost], поэтому у меня они конфликтовали. Я писал все методы под одним из атрибутов

Алексей
Алексей
6 месяцев назад

Добрый день.
public interface IProduct
  {
    //…
    void Product GetProduct(int id); <- может public ?
    void UpdateProduct(Product product);
  }

5
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x