Учебный курс по WebMatrix, глава 8. Работа с данными

Это продолжение учебного курса по WebMatrix. Предыдущие части руководство можно найти здесь:

В этой главе описывается метод доступа к данным в базе данных и отображения их с помощью веб-страниц ASP.NET.

Будет рассмотрено

  • создание базы данных;
  • подключение к базе данных;
  • отображение данных на веб-странице;
  • вставка, обновление и удаление записей в базе данных.

В данной главе рассматриваются следующие новые аспекты:

  • работа с базой данных Microsoft SQL Server Compact Edition (Входит в WebMatrix);
  • работа с SQL-запросами;
  • класс Database;
  • вспомогательные объекты WebGrid.

Кратко о базах данных

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

Обычный способ представления подобных данных — таблица со строками и столбцами. Применительно к базам данных строки часто называют записями. Каждый столбец (порой именуемый полями) содержит значение для каждого типа данных: имя, фамилия и т. д.

ID

FirstName (имя)

LastName (фамилия)

Address (адрес)

Email (адрес электронной почты)

Phone (телефон)

1

Иван

Иванов

127000, Москва, Ленина 85 - 33

ivan@mail.ru

34567890

2

Петр

Петров

454000, Челябинск, Тимирязева 25 - 13

petr@mail.ru

45678900

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

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

Реляционные базы данных

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

Эта глава не ставит своей целью глубокое изучение баз данных. Вместе с тем, получить некоторое представление о них было бы полезно. В реляционной базе данных информация логически разнесена по отдельным таблицам. Например, база данных учебного заведения может содержать отдельные таблицы для учащихся и предлагаемых классных занятий. Программное обеспечение баз данных (например, SQL Server) поддерживает эффективные команды, позволяющие динамически устанавливать отношения между таблицами. Например, в реляционной базе данных можно установить логическое отношение между учащимися и классами для создания расписания. Хранение данных в отдельных таблицах упрощает структуру таблиц и уменьшает потребность в заполнении таблиц избыточными данными.

Создание базы данных

Ниже приводится описание процедуры создания базы данных под названием SmallBakery с помощью средства разработки баз данных SQL Server Compact, включенного в состав WebMatrix. Создать базу данных можно и с помощью кода, однако более типичным является создание баз данных и таблиц баз данных с помощью средства разработки, такого как WebMatrix.

1. Запустите WebMatrix и на странице быстрого запуска щелкните «Сайт на основе шаблона».

2. Выберите «Пустой сайт» и в поле «Имя сайта» введите SmallBakery, затем нажмите кнопку OK. Сайт будет создан и отображен в WebMatrix.

3. Перейдите в рабочую область «Базы данных» и щелкните по кнопке «Добавить базу данных на сайт». Будет создана одноименная с сайтом база данных.

4. 5.На левой панели разверните узел SmallBakery.sdf и щелкните «Таблицы», после чего на ленте выберите «Создать таблицу».

В результате Вы окажетесь во встроенном конструкторе таблиц WebMatrix:

clip_image002

5. На панели «Свойства столбца» в строке (Имя) введите ID.

6. В полях «Идентификатор» и «Первичный ключ» выставите значение true. Свойство «Первичный ключ» говорит само за себя, а вотсвойство «Идентификатор» указывает дополнительно и на то, что база данных автоматически будет создавать идентификационный номер для каждой новой записи и присваивать ей следующий номер. Так как у нас автоматически переключилось свойство «Разрешить значения NULL» на False и стоит «Тип данных» bigint – нумерация будет начата с 1 и является целым числом.

7. Щелкните «Создать столбец» и назовите его Name. Запретите значения NULL, чтоб название не могло остаться пустым и задайте значение «Тип данных» nchar . Это укажет базе данных, что данные в этом столбце будут представлять собой строку заданной длины (обозначена префиксом "n").

8. Аналогично создайте столбец Description с такими же параметрами, как и у Name.

9. Аналогично создайте столбец Price с типом данных money.

Мы получим структуру представленную на скриншоте ниже:

clip_image004

Сохраним ее нажатием Ctrl+S и назовем Products.

Добавление данных в базу данных.

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

1. На левой панели в рабочей области «Базы данных» выберите только что сохраненную таблицу и в области редактирования введите следующие записи:

Name (название)

Description (описание)

Price (цена)

Хлеб

Свежий хлеб выпекается ежедневно

2,99

Клубничный пирог

Начинен натуральной клубникой из собственного хозяйства

9,99

Яблочный пирог

Уступает только пирогу вашей матушки

12,99

Ореховый пирог

Для любителей ореха-пекана

10,99

Лимонный пирог

Приготовлен из лучших лимонов в мире

11,99

Кексы

Понравятся детям и их родителям

7,99

Следует помнить, что в столбец Id вводить ничего не требуется. При создании столбца Id свойству «Идентификатор» было присвоено значение true, поэтому столбец будет заполняться автоматически.

По окончании ввода, конструктор будет выглядеть так:

clip_image006

Отображение данных из базы данных.

Создав базу данных с данными в ней, можно отобразить эти данные на веб-странице ASP.NET. Чтобы выбрать отображаемые строки таблицы, используется инструкция SQL, представляющая собой команду, передаваемую в базу данных.

1. На левой панели щелкните рабочую область «Файлы» и создайте CSHTML-страницу в корневом каталоге, назвав ее ListProducts.cshtml.

2. Замените существующую разметку следующим кодом:

@{

    var db = Database.Open("SmallBakery");

    var selectQueryString = "SELECT * FROM Products ORDER BY Name";

 }

<!DOCTYPE html>

<html>

  <head>

    <title>Продукция малой булочной-пекарни</title>

    <style>

        h1 {font-size: 14px;}

        table, th, td {

          border: solid 1px #bbbbbb;

          border-collapse:collapse;

          padding:2px;

        }

     </style>

  </head>

  <body>

    <h1>Продукция малой булочной-пекарни</h1>

    <table>

        <thead>

            <tr>

                <th>Id</th>

                <th>Продукт</th>

                <th>Описание</th>

        <th>Цена</th>

            </tr>

        </thead>

        <tbody>

            @foreach (var row in db.Query(selectQueryString)){

             <tr>

                <td>@row.Id</td>

                    <td>@row.Name</td>

                    <td>@row.Description</td>

                    <td>@row.Price</td>

             </tr>

            }

        </tbody>

    </table>

  </body>

</html>

В первом блоке кода открывается созданный ранее файл SmallBakery.sdf (база данных). Метод Database.Open предполагает, что SDF-файл находится в папке App_Data веб-сайта.

Примечание. Папка App_Data — это особая папка в ASP.NET, которая служит для хранения файлов данных. Дополнительные сведения см. в разделе Подключение к базе данных далее в этой главе. Данная папка создается автоматически, при создании Базы Данных.

Затем в базу данных передается запрос с использованием инструкции SQL Select:

SELECT * FROM Products ORDER BY Name

В этой инструкции значение Products определяет таблицу, из которой следует запросить данные. Знак * указывает, что запрос должен вернуть все столбцы в таблице (если требуется отобразить лишь некоторые столбцы, их можно перечислить по отдельности через запятую). Предложение Order By указывает, каким образом следует сортировать данные (в данном случае, по столбцу Name). Это значит, что данные будут отсортированы в алфавитном порядке по значению в столбце Name для каждой строки.

В текстовой области страницы разметка создает HTML-таблицу, которая будет служить для отображения данных. Для получения каждой строки данных, возвращенной запросом, внутри элемента tbody используется цикл foreach. Для каждой строки данных в HTML-таблице создается строка (элемент tr). Затем для каждого столбца в HTML-таблице создаются ячейки (td). При каждом прохождении цикла следующая имеющаяся строка базы данных обозначается переменной row (это задается в инструкции foreach). Для извлечения отдельного столбца из строки можно использовать row.Name, row.Description или любой другой требуемый заголовок столбца.

3. Откройте страницу в браузере:

clip_image008

Язык структурированных запросов (SQL)

SQL — это язык, используемый в большинстве реляционных баз данных для управления данными. Он включает в себя команды, позволяющие извлекать и обновлять данные, а также создавать и изменять таблицы баз данных и управлять ими. SQL отличается от языка программирования (подобного тому, который используется в WebMatrix), поскольку предназначение SQL — сообщить базе данных, что от нее требуется, а база данных сама выберет способ извлечения данных или выполнения операции. Ниже приведены примеры некоторых команд SQL и пояснения, какие операции выполняются с их помощью.

SELECT Id, Name, Price FROM Products WHERE Price > 10,00 ORDER BY Name

Извлечение столбцов Id,Name и Price из записей в таблице Products, если значение Price больше 10, и возвращение результатов в алфавитном порядке значений в столбце Name. Эта команда возвращает результирующий набор, который содержит записи, отвечающие условиям, либо пустой набор, если таких записей нет.

INSERT INTO Products (Name, Description, Price) VALUES ("Круассан", "Слоеное наслаждение", 1,99)

Вставка новой записи в таблицу Products, присвоение столбцу Name значения "Круассан", а столбцу Description — значения "Слоеное наслаждение" с указанием цены в 1,99.

DELETE FROM Products WHERE ExpirationDate < "01/01/2008"

Удаление из таблицы Products записей, в столбце срока годности которых указана дата ранее 1 января 2008 года (подразумевается, естественно, что в таблице Products имеется такой столбец). В данном случае дата введена в формате ММ/ДД/ГГГГ, однако ее следует вводить в формате, соответствующем региональным и языковым особенностям.

Команды InsertInto и Delete не возвращают результирующие наборы. Вместо этого они возвращают число, показывающее, сколько записей было затронуто ими.

Процессам, запрашивающим некоторые из этих операций (такие как вставка и удаление записей), в базе данных должны быть предоставлены соответствующие разрешения. Именно поэтому при подключении к рабочим базам данных часто приходится вводить имя пользователя и пароль.

Команд в SQL — сотни, но все они строятся по подобной схеме. Команды SQL можно применять для создания таблиц баз данных, подсчета числа записей в таблице, расчета цен и выполнения многих других операций.

Вставка данных в базу данных

В этом разделе демонстрируется способ создания страницы, которая позволяет пользователям добавить новый продукт в таблицу Products базы данных. После вставки новой записи продукта на странице ListProducts.cshtml, созданной в предыдущем разделе, отображается обновленная таблица.

Эта страница включает в себя проверку, позволяющую гарантировать, что пользователь вводит данные допустимые для определенной базы данных. Например, код на странице обеспечивает ввод значений во все обязательные столбцы.

Примечание. Процессам, запрашивающим некоторые из этих операций (такие как вставка и удаление записей), в базе данных должны быть предоставлены соответствующие разрешения. При подключении к рабочим базам данных, в отличие от тестовой базы данных, с которой сейчас выполняется работа в WebMatrix, часто приходится вводить имя пользователя и пароль.

1. Создайте новый CSHTML-файл на веб-сайте с именем InsertProducts.cshtml.

2. Замените существующую разметку следующим кодом:

@{

    var db = Database.Open("SmallBakery");

    var Name = Request["Name"];

    var Description = Request["Description"];

    var Price = Request["Price"];

    if (IsPost) {

         // Считывание названия продукта.

        Name =Request["Name"];

        if (Name.IsEmpty()) {

           ModelState.AddError("Name", "Введите названиепродукта.");

        }

        // Считывание описания продукта.

        Description = Request["Description"];

        if (Description.IsEmpty()) {

          ModelState.AddError("Description",

                "Введите описание продукта.");

         }

        // Считывание цены продукта.

        Price = Request["Price"];

        if (Price.IsEmpty()) {

          ModelState.AddError("Price", "Введите цену на продукт.");

        }

        // Определение запроса вставки. Значения, присваемые

        // столбцам в таблице Products определяются как параметры

        // (используя ключевое слово VALUES).

        if (ModelState.IsValid) {

            var insertQuery = "INSERT INTO Products (Name, Description, Price) "+

                "VALUES (@0, @1, @2)";

            db.Execute(insertQuery, Name, Description, Price);

            // Отображение страницы со списком продуктов.

            Response.Redirect(@Href("~/ListProducts"));

        }

    }

}

<!DOCTYPE html>

<html>

<head>

    <title>Добавление продуктов</title>

    <style type="text/css">

       h1 {font-size: 14px;}

       label { float: left; width: 8em; text-align: right;

                margin-right: 0.5em;}

       fieldset { padding: 1em; border: 1px solid; width: 35em;}

       legend { padding: 2px 4p; border: 1px solid; font-weight: bold;}

       .errorDisplay { font-weight:bold; color:red; font-size:11pt; }

    </style>

</head>

<body>

    <h1>Добавление нового продукта</h1>

    <div class=".errorDisplay">

        @Html.ValidationSummary("Ошибки в добавляемом:")

    </div>

    <form method="post" action="">

        <fieldset>

            <legend>Добавление продукта</legend>

            <div>

                <label>Название:</label>

                <input name="Name" type="text" size="50" value="@Name"/>

            </div>

            <div>

                <label>Описание:</label>

                <input name="Description" type="text" size="50"

                    value="@Description" />

            </div>

            <div>

                <label>Цена:</label>

                <input name="Price" type="text" size="50" value="@Price"/>

            </div>

            <div>

                <label>&nbsp;</label>

                <input type="submit" value="Вставить" class="submit"/>

            </div>

        </fieldset>

    </form>

</body>

</html>

Текстовая область страницы содержит HTML-форму с тремя текстовыми полями, в которые пользователи могут вводить название, описание и цену. Когда пользователь нажимает кнопку Вставить, код в верхней части страницы открывает соединение с базой данных SmallBakery.sdf. Затем введенные пользователем значения извлекаются из объекта Request (запрос) и назначаются локальным переменным.

Для проверки, во все ли обязательные столбцы пользователь ввел значения, выполняется следующая операция:

        Name =Request["Name"];

        if (Name.IsEmpty()) {

           ModelState.AddError("Name", "Введите названиепродукта.");

        }

Если значение в столбце Name отсутствует, применяется метод AddError вспомогательного объекта ModelState; в него передается сообщение об ошибке. Эта операция повторяется для каждого столбца, который требуется проверить. По завершении проверки всех столбцов выполняется следующий тест:

if (ModelState.IsValid) {

При положительном результате проверки всех столбцов (все столбцы заполнены) можно перейти к созданию инструкции SQL для вставки и к последующему ее выполнению, как показано ниже:

var insertQuery = "INSERT INTO Products (Name, Description, Price) "+

                "VALUES (@0, @1, @2)";

Инструкция включает заполнители параметров (@0, @1, @2) для вставляемых значений.

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

Для выполнения запроса используется эта инструкция, в которую передаются переменные, содержащие значения для подстановки на место заполнителей.

db.Execute(insertQuery, Name, Description, Price);

После выполнения инструкции InsertInto пользователь перенаправляется на страницу со списком продуктов с помощью следующей строки:

Response.Redirect(@Href("~/ListProducts"));

Если проверка дала отрицательный результат, то от вставки следует воздержаться. Вместо этого применяется имеющийся на странице вспомогательный объект для отображения накопившихся сообщений об ошибках (если таковые имеются):

        @Html.ValidationSummary("Ошибки в добавляемом:")

3. Просмотрите страницу в браузере и заполните ее, не заполняя поле «Цена»:

clip_image010

4. Нажмите «Вставить» и Вы увидите сообщение об ошибке. Никаких записей в базе данных не создается.

clip_image012

5. Введите цену и нажмите «Вставить». Откроется страница ListProducts.cshtml с новой записью:

clip_image014

Обновление данных в базе данных

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

1. Создайте новый CSHTML-файл на веб-сайте с именем EditProducts.cshtml и замените существующую разметку в файле следующим кодом:

@{

    var db = Database.Open("SmallBakery");

    var selectQueryString = "SELECT * FROM Products ORDER BY Name";

}

<!DOCTYPE html>

<html>

<head>

    <title>Изменение продуктов</title>

    <style type="text/css">

        h1 {font-size: 14px;}

        td { background-color: #cccccc; padding:4px;}

    </style>

</head>

<body>

    <h1>Изменение продукции малой булочной-пекарни</h1>

    <table>

      <thead>

        <tr>

          <th>&nbsp;</th>

          <th>Name</th>

          <th>Description</th>

          <th>Price</th>

        </tr>

      </thead>

      <tbody>

        @foreach (var row in db.Query(selectQueryString)) {

          <tr>

            <td><a href="@Href("~/UpdateProducts", row.Id)">Правка</a></td>

            <td>@row.Name</td>

            <td>@row.Description</td>

            <td>@row.Price</td>

          </tr>

        }

      </tbody>

    </table>

</body>

</html>

Единственное отличие данной страницы от ранее созданной ListProducts.cshtml состоит в том, что HTML-таблица на ней включает в себя дополнительный столбец, в котором отображается ссылка Правка. Эта ссылка служит для перехода на страницу UpdateProducts.cshtml (будет создана вслед за данной страницей), на которой можно редактировать выбранную запись.

Код ниже используется для создания ссылки Правка:

<td><a href="@Href("~/UpdateProducts", row.Id)">Правка</a></td>

Он создает HTML-привязку (элемент a), атрибут href которой задается динамически. Атрибут href указывает, какую страницу отображать, когда пользователь щелкнет ссылку. Он также передает в ссылку значение Id текущей строки. При запуске страницы ее источник может содержать следующие ссылки:

  • <a href="UpdateProducts/1">Правка</a></td>
  • <a href="UpdateProducts/2">Правка</a></td>
  • <a href="UpdateProducts/3">Правка</a></td>

Заметьте, что для атрибута href задано значение UpdateProducts/n, где n — номер продукта. Когда пользователь щелкает одну из этих ссылок, в результате получается примерно такой URL-адрес:

https://localhost:32985/EditProducts/4

Другими словами, номер подлежащего изменению продукта передается в URL-адрес.

2. Просмотрите страницу в браузере. На этой странице данные отображаются в формате, сходном с тем, что показан на следующем рисунке:

clip_image016

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

3. Создайте новый CSHTML-файл на веб-сайте с именем UpdateProducts.cshtml.

4. Замените существующую разметку в файле следующим кодом:

@{

    var db = Database.Open("SmallBakery");

    var selectQueryString = "SELECT * FROM Products WHERE Id=@0";

    var ProductId = UrlData[0];

        if (ProductId.IsEmpty()) {

         Response.Redirect(@Href("~/EditProducts"));

     }

        var row = db.QuerySingle(selectQueryString, ProductId);

        var Name = row.Name;

        var Description = row.Description;

        var Price = row.Price;

            if (IsPost) {

         Name = Request["Name"];

         if (String.IsNullOrEmpty(Name)) {

           ModelState.AddError("Name", "Введите название продукта.");

         }

        Description = Request["Description"];

        if (String.IsNullOrEmpty(Description)) {

          ModelState.AddError("Description",

              "Введите описание продукта.");

        }

        Price = Request["Price"];

        if (String.IsNullOrEmpty(Price)) {

          ModelState.AddError("Price", "Введите цену на продукт.");

        }

    if (ModelState.IsValid) {

            var updateQueryString =

              "UPDATE Products SET Name=@0, Description=@1, Price=@2 WHERE Id=@3";

            db.Execute(updateQueryString, Name, Description, Price, ProductId);

            Response.Redirect(@Href("~/EditProducts"));

        }

    }

}

<!DOCTYPE>

<html>

<head>

    <title>Добавление продуктов</title>

    <style type="text/css">

    h1 {font-size: 14px;}

       label { float: left; width: 8em; text-align: right;

                margin-right: 0.5em;}

       fieldset { padding: 1em; border: 1px solid; width: 35em;}

    legend { padding: 2px 4p; border: 1px solid; font-weight: bold;}

       .errorDisplay { font-weight:bold; color:red; }

    </style>

</head>

<body>

    <h1>Обновление продукта</h1>

    <div class="errorDispla">

        @Html.ValidationSummary("Ошибки в добавляемом:")

    </div>

    <form method="post" action="">

        <fieldset>

            <legend>Обновление продукта</legend>

            <div>

                <label>Название:</label>

                <input name="Name" type="text" size="50" value="@Name"/>

            </div>

            <div>

                <label>Описание:</label>

                <input name="Description" type="text" size="50"

                   value="@Description" />

            </div>

            <div>

                <label>Цена:</label>

                <input name="Price" type="text" size="50" value="@Price"/>

            </div>

            <div>

                <label>&nbsp;</label>

                <input type="submit" value="Обновить" class="submit"/>

            </div>

        </fieldset>

    </form>

</body>

</html>

Текстовая область страницы включает в себя HTML-форму, в которой отображается продукт и где пользователи могут вносить изменения. Для отображения продукта применяется следующая инструкция SQL:

SELECT * FROM Products WHERE Id=@0

Операция выберет продукт, идентификатор которого совпадает со значением, переданным в параметре @0 (поскольку Id является первичным ключом и потому должен быть уникальным, этим методом можно выбрать только одну запись продукта). Чтобы передать значение идентификатора в эту инструкцию Select, можно считать значение, передаваемое на страницу в качестве части URL-адреса, с помощью следующего синтаксиса:

    var ProductId = UrlData[0];

Для фактического извлечения записи продукта применяется метод QuerySingle, который возвращает только одну запись:

var row = db.QuerySingle(selectQueryString, ProductId);

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

var Name = row.Name;

var Description = row.Description;

var Price = row.Price;

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

<input name="Name" type="text" size="50" value="@Name"/>

Эта часть кода отображает запись продукта, которую требуется обновить. Когда запись отобразится, пользователь сможет редактировать отдельные столбцы.

Когда пользователь передает форму, нажав кнопку Обновить, запускается выполнение кода в блоке if(IsPost). При этом значения, введенные пользователем, извлекаются из объекта Request и сохраняются в переменных; также выполняется проверка, все ли столбцы заполнены. При положительном результате проверки код создает следующую инструкцию SQL Update:

UPDATE Products SET Name=@0, Description=@1, Price=@2, WHERE ID=@3

В инструкции SQL Update указываются все столбцы, которые требуется обновить, и значения, которые им необходимо задать. В этом коде значения задаются с помощью заполнителей параметров @0, @1, @2 и т. д. (как отмечалось ранее, в интересах безопасности значения всегда следует передавать в инструкцию SQL с помощью параметров).

При вызове метода db.Execute содержащие значения переменные передаются в порядке, соответствующем параметрам в инструкции SQL:

db.Execute(updateQueryString, Name, Description, Price, ProductId);

Для перенаправления пользователя на страницу редактирования после выполнения инструкции Update можно вызвать приведенный ниже метод:

Http.Redirect("EditProducts");

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

Сохраните страницу и запустите страницу EditProducts.cshtml (не страницу обновления) и нажмите кнопку Правка, чтобы выбрать продукт, который требуется изменить. Откроется страница UpdateProducts.cshtml с выбранной записью:

clip_image018

5. Внесем изменения и автоматически перейдем к нашей измененной таблице, как на следующих скриншотах:

clip_image020

clip_image022

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

В этом разделе демонстрируется способ удаления продукта из таблицы Products базы данных. Пример состоит из двух страниц. На первой странице выбирают запись, которую требуется удалить. Подлежащая удалению запись затем отображается на второй странице, что дает пользователю возможность подтвердить свое намерение удалить ее.

1. Создайте новый CSHTML-файл на веб-сайте с именем ListProductsForDelete.cshtml. и замените существующую разметку следующим кодом:

@{

  var db = Database.Open("SmallBakery");

  var selectQueryString = "SELECT * FROM Products ORDER BY Name";

}

<!DOCTYPE html >

<html>

<head>

    <title>Удаление продукта</title>

</head>

<body>

  <h1>Удаление продукта</h1>

  <form method="post" action="" name="form">

    <table border="1">

      <thead>

        <tr>

          <th>&nbsp;</th>

          <th>Name</th>

          <th>Description</th>

          <th>Price</th>

        </tr>

      </thead>

      <tbody>

        @foreach (var row in db.Query(selectQueryString)) {

          <tr>

            <td><a href="@Href("~/DeleteProduct", row.Id)">Удалить</a></td>

            <td>@row.Name</td>

            <td>@row.Description</td>

            <td>@row.Price</td>

          </tr>

        }

      </tbody>

    </table>

  </form>

</body>

</html>

Эта страница похожа на созданную ранее EditProducts.cshtml. Однако вместо ссылки Правка для каждого продукта отображается ссылка Удалить. Ссылка Удалить создается с помощью следующего внедренного кода в разметке:

<a href="@Href("~/DeleteProduct", row.Id)">Удалить</a>

Он создает URL-адрес, который при щелчке ссылки выглядит следующим образом.

/DeleteProduct/4">/DeleteProduct/4">/DeleteProduct/4">/DeleteProduct/4">/DeleteProduct/4">https://<сервер>/DeleteProduct/4

Этот URL-адрес вызывает страницу DeleteProduct.cshtml (которая сейчас будет создана) и передает идентификатор продукта, подлежащего удалению (в данном случае — 4).

2. Сохраните файл, но не закрывайте его и создайте еще один CHTML-файл, назовите его DeleteProduct.cshtml и замените содержимое следующим кодом:

@{

  var db = Database.Open("SmallBakery");

  var ProductId = UrlData[0];

  var prod = db.QuerySingle("SELECT * FROM PRODUCTS WHERE ID = @0", ProductId);

  if (IsPost && !ProductId.IsEmpty()) {

    var deleteQueryString = "DELETE FROM Products WHERE Id=@0";

    db.Execute(deleteQueryString, ProductId);

    Response.Redirect("~/ListProductsForDelete");

  }

}

<!DOCTYPE html >

<html>

<head>

    <title>Удаление продукта</title>

</head>

<body>

  <h1>Подтверждение удаления продукта</h1>

  <form method="post" action="" name="form">

    <p>Действительно удалить следующий продукт?</p>

    <p>Name: @prod.Name <br/>

       Description: @prod.Description <br/>

       Price: @prod.Price</p>

    <p><input type="submit" value="Удалить" /></p>

  </form>

</body>

</html>

Эта страница вызывается ListProductsForDelete.cshtml и позволяет пользователю подтвердить свое намерение удалить тот или иной продукт. Для отображения продукта, подлежащего удалению, из URL-адреса извлекается идентификатор этого продукта с помощью следующего кода:

var ProductId = UrlData[0];

Для фактического же удаления записи на странице отображается предложение нажать кнопку. Это важная мера безопасности. Важные операции на веб-сайте, такие как обновление или удаление данных, должны всегда выполняться с помощью операции POST, а не GET. Если сайт настроен таким образом, что удаление может выполняться посредством операции GET, то кто угодно сможет передать URL-адрес типа https://<сервер>/DeleteProduct/4 и удалить из базы данных все, что пожелает. Добавление функции подтверждения и программирование страницы на выполнение удаления только посредством операции POST повышает защищенность сайта.

Операция фактического удаления выполняется с помощью следующего кода, который сначала проверяет, является ли эта операция операцией POST и указан ли идентификатор.

if (IsPost && !ProductId.IsEmpty()) {

    var deleteQueryString = "DELETE FROM Products WHERE Id=@0";

    db.Execute(deleteQueryString, ProductId);

    Response.Redirect("~/ListProductsForDelete");

  }

Код запускает инструкцию SQL, которая удаляет указанную запись и затем перенаправляет пользователя на страницу со списком продукции.

3. Запустите ListProductsForDelete.cshtml в браузере:

clip_image024

4. Щелкните ссылку Удалить одного из продуктов. Откроется страница DeleteProduct.cshtml для подтверждения намерения удалить данную запись:

clip_image026

5. Нажмите кнопку Удалить. Запись продукта удаляется, а страница обновляется с измененным списком продукции:

clip_image028

Благодарности

Благодарим Виталия Коробцева, руководителя инновационных проектов “ООО Валькирия”, за неоценимую помощь в подготовке этого руководства.