Редактирование и удаление данных

Последнее обновление: 11.04.2022

Продолжим работу с проектом из прошлой темы и добавим в него возможность редактирования и удаления данных. И прежде всего изменим представление Index.cshtml, добавив в него ссылки:

@model IEnumerable<MvcApp.Models.User>

<h2>Список пользователей</h2>
<p><a asp-action="Create">Добавить пользователя</a></p>
<table class="table">
     <tr><th>Имя</th><th>Возраст</th><th></th><th></th></tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>@item.Name</td>
            <td>@item.Age</td>
            <td>
                <a asp-action="Edit" asp-controller="Home" asp-route-id="@item.Id">Изменить</a>
            </td>
            <td>
                <form asp-controller="Home" asp-action="Delete" method="post"  asp-route-id="@item.Id">
                    <input type="submit" value="Удалить" />
                </form>
            </td>
        </tr>
    }
</table>

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

Редактирование и удаление данных в Entity Framework в ASP.NET Core MVC и C#

Удаление

Для создания инфраструктуры удаления добавим в контроллер следующий метод:

[HttpPost]
public async Task<IActionResult> Delete(int? id)
{
    if (id != null)
    {
        User? user = await db.Users.FirstOrDefaultAsync(p => p.Id == id);
        if (user != null)
        {
            db.Users.Remove(user);
            await db.SaveChangesAsync();
            return RedirectToAction("Index");
        }
    }
	return NotFound();
}

Метод принимает параметр id, с помощью которого получаем удаляемый объект из БД и, если он существует, удаляем его с помощью метода db.Users.Remove(). Данный метод генерирует sql-выражение DELETE, которое выполняется вызовом db.SaveChangesAsync().

Стоит отметить, что данный метод Delete обрабатывает только запросы типа POST. Почему? Дело в том, что использование get-методов не безопасно. Например, нам могут прислать письмо с картинкой:

<img src="http://адрес_нашего_сайта/Home/Delete/1" />

И при открытии письма на сервер будет отправлен get-запрос. И если бы метод Delete обрабатывал бы get-запросы, то объект с id=1 был бы удален из базы данных.

Именно поэтому данный метод обрабатывает запросы POST, а для обращения к этому методу в представлении определена не просто ссылка, а форма с кнопкой, по нажатию на которую выполняется post-запрос.

И еще надо отметить, что в post-методе Delete мы можем произвести небольшую оптимизацию. Иногда бывает важно узнать перед удалением, а есть ли такой объект в БД. Однако в данном случае мы получаем два запроса к бд - один на получение объекта и второй на его удаление. И мы можем оптимизировать метод следующим образом:

[HttpPost]
public async Task<IActionResult> Delete(int? id)
{
    if (id != null)
    {
        User user = new User { Id = id.Value };
        db.Entry(user).State = EntityState.Deleted;
        await db.SaveChangesAsync();
        return RedirectToAction("Index");
    }
	return NotFound();
}

В данном случае нам важен только id объекта. Поэтому создаем новый объект user и устанавливаем у него состояние Deleted: db.Entry(user).State = EntityState.Deleted;. Это выражение опять же сгенерирует sql-выражение DELETE.

Редактирование

Для редактирования объекта добавим в контроллер следующую пару методов:

public async Task<IActionResult> Edit(int? id)
{
    if(id!=null)
    {
        User? user = await db.Users.FirstOrDefaultAsync(p=>p.Id==id);
        if (user != null) return View(user);
    }
    return NotFound();
}
[HttpPost]
public async Task<IActionResult> Edit(User user)
{
    db.Users.Update(user);
    await db.SaveChangesAsync();
    return RedirectToAction("Index");
}

GET-версия метода Edit возвращает форму с данными объекта, которые пользователь может отредактировать. А post-версия Edit получает отредактированные данные в виде объекта user и с помощью метода db.Users.Update(user) для этих данных будет генерироваться sql-выражение UPDATE, которое будет выполнено вызовом db.SaveChangesAsync()

И также добавим для этих методов в папку Views/Home представление Edit.cshtml:

@model MvcApp.Models.User

<h2>Редактирование пользователя</h2>
<form asp-action="edit" asp-controller="home" asp-route-id="@Model.Id">
    <p>
        <label asp-for="Name">Имя</label><br />
        <input type="text" asp-for="Name" />
    </p>
    <p>
        <label asp-for="Age">Возраст</label><br />
        <input type="number" asp-for="Age" />
    </p>
    <p>
        <input type="submit" value="Сохранить" />
    </p>
</form>

Эта форма аналогична форме в представлении для создания нового объекта за исключением атрибута asp-route-id="@Model.Id". Установка этого атрибута позволяет при отправке данных вместе с ними также отправить и значение Model.Id. Без этого значения Entity Framework не сможет обновить соответствующую модель в базе данных.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850