Как написать запрос для бд из с

от admin

Как написать запрос для бд из с

Для выполнения запросов к базе данных SQLite применяется класс SqliteCommand , который представляет реализацию интерфейса System.Data.IDbCommand . Для создания объекта SqliteCommand можно использовать один из его конструкторов:

SqliteCommand(String) : создает объект SqliteCommand, в конструктор которого передается выполняемое выражение SQL

SqliteCommand(String, SqliteConnection) : создает объект SqliteCommand, в конструктор которого передается выполняемое выражение SQL и используемое подключение к базе данных в виде объекта SqliteConnection

SqliteCommand(String, SqliteConnection, SqliteTransaction) : третий параметр представляет применяемую транзакцию в виде объекта SqliteTransaction

Альтернативным способом создания объекта SqliteCommand представляет метод CreateCommand90 класса SqliteConnection:

Для конфигурации объекта SqliteCommand можно использовать ряд его свойств, некоторые из них:

CommandText : хранит выполняемую команду SQL

CommandTimeout : хранит временной интервал в секундах, после которого SqliteCommand прекращает попытки выполнить команду. По умолчанию равен 30 секундам. Значение 0 представляет отстутсвие интервала.

Parameters : предствляет параметры команды

Connection : предоставляет используемое подключение SqliteConnection

Например, установим свойства подключения и выполняемой команды:

Чтобы выполнить команду, необходимо применить один из методов SqliteCommand:

ExecuteNonQuery : выполняет sql-выражение и возвращает количество измененных записей. Подходит для sql-выражений INSERT, UPDATE, DELETE, CREATE.

ExecuteReader() : выполняет sql-выражение и возвращает считанные из таблицы строки. Подходит для sql-выражения SELECT.

ExecuteScalar() : выполняет sql-выражение и возвращает одно скалярное значение, например, число. Подходит для sql-выражения SELECT в паре с одной из встроенных функций SQL, как например, Min, Max, Sum, Count.

Создание таблицы

Для создания базы данных применяется SQL-команда CREATE TABLE , после которой указывается имя создаваемой таблицы и в скобках определения столбцов.

Например, создадим таблицу «Users», которая будет иметь три столбца — _id (уникальный идентификатор), Name (имя), Age (возраст):

После выполнения команды в базе данных можно будет найти таблицу Users:

Для просмотра бд SQLite можно использовать специальный инструмент — DB Browser for SQLite.

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

Теперь добавим в выше созданную таблицу Users новый объект:

Для вставки объекта используется sql-выражение INSERT, которое имеет следующий синтаксис:

В ранее созданной таблице Users определены три столбца — __id и Age, которые хранят целое число, и Name, который хранит строку. Поэтому соответственно мы добавляем для столбца Name значение ‘Tom’, а для столбца Age число 36.

Здесь метод ExecuteNonOuery() возвращает число затронутых строк (в данном случае добавленных в таблицу объектов). Хотя нам необязательно возвращать результат метода, но данный результат может использоваться в качестве проверки, что операция, в частности, добавление, прошла успешно.

После добавления данных мы сможем их увидеть через DB Browser for SQLite:

Добавление в БД SQLite через SqliteCommand в C# и .NET

Подобным образом можно добавить несколько объектов:

Обновление объектов

Для обновления применяется sql-команда UPDATE, которое имеет следующий синтаксис:

Применим эту команду:

Здесь обновляется строка, в которой Name=Tom, то есть выше добавленный объект. Если в таблице будет несколько строк, у которых Name=Tom, то обновятся все эти строки.

Удаление

Удаление производится с помощью sql-выражения DELETE, которое имеет следующий синтаксис:

Удалим, например, всех пользователей, у которых имя Tom:

Во всех трех случаях фактически меняется только sql-выражение, а остальная логика остается неизменной. И мы также можем выполнять сразу несколько операций:

Программирование на C, C# и Java

Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы

ОСТОРОЖНО МОШЕННИКИ! В последнее время в социальных сетях участились случаи предложения помощи в написании программ от лиц, прикрывающихся сайтом vscode.ru. Мы никогда не пишем первыми и не размещаем никакие материалы в посторонних группах ВК. Для связи с нами используйте исключительно эти контакты: vscoderu@yandex.ru, https://vk.com/vscode

MySQL и C# — работаем с базой данных. Запросы SELECT

В видеоуроке рассмотрим работу с базой данных MySQL на примере SELECT-запросов из программы, написанной на языке программирования C#. В статье вы найдёте исходные коды примеров из видео.

В видео показано выполнение запросов выборки (SELECT) к БД с помощью C#. Рассказывается про получение, как одного значения из базы, так и нескольких столбцов и строк.

Исходный код примера с получением одного значения из базы с помощью метода ExecuteScalar():

Words are DUST

Итак 🙂 Ниже будет пост, бьющий все рекорды просмотров на codepaste. В свое время я почему-то ничего толкового не нашел, было много экспериментов. Теперь я хочу показать тебе маленький, но очень гордый проект для работы с БД MySQL

Предисловие и приготовления

  1. Скачивание и установка MySQL-сервера (если приложение работает с локальной базой)
  2. Конфигурация графического интерфейса БД (phpMyAdmin — веб-морда, пригодится, если помимо MySQL-сервера у нас стоит еще и http-сервер(Apache, например). Так будет, если вы берете MySQL из состава Denwer. Иначе, если тебя интересует только БАЗА, то рекомендую dbForge Studio for MySQL)
  3. Конфигурация базы (собственно, описание ее структуры, связей, типов, состава полей и т.п. ) или перенос дампа с существующей базы
  4. Написание программы-клиента.

Реализация

Ок, все вводые выполнили, теперь можно приступать. Извращаться не будем, для наглядности пишем в одном файле. Сначала ничего интересного — описываем подключаемые библиотеки, файлы и пространства имен:

А вот теперь заполняем основные константы для подключения к базе и переходим к телу функции main. (Знатоков PHP сейчас начнет хватать за пятку де-жа-вю)

Итак, обращу твое внимание. Мы подключились к базе, уже без палева провели первый запрос. Да. Это функция mysql_query(дескриптор,»Запрос»);. В данном случае, мы подключились и сказали:«Дорогая База Данных! Пожалуйста, сформируй кодировку вывода для соединения link как кириллическую (cp1251)». Тем самым мы, консоль и база говорят на одном языке (кодировке). Теперь можем смело приступать к более осмысленным вещам.

Пусть у тебя есть некая таблица со статьями (articles), в ней есть поля автор (Authors) и название стати (Title). Попробуем «вытащить» из базы названия всех статей, автор которых, к примеру. Хватит это терпеть! Пусть будет Жириновский.

Это не безопасный вариант кода, если у нас какая-то операция не удастся, то программа вылетит с ошибкой. Давай еще раз то же самое, но с проверкой на успешность.

Постскриптум

Функций, доступных разработчикам, много. Мануалы по конкретным задачам гуглятся на ура. Я же ставил себе целью показать некий «Hello, World!», маленький, но уже обросший всем необходимым, 100% рабочий проект.

ASP.NET MVC – работаем с MySQL через ADO.NET

Уже, наверное, раза три подбираюсь к ASP.NET MVC. После десяти лет с ASP.NET WebForms немного сложно переходить именно к технологии MVC, поскольку отличий столько, что скорее проще перечислить, что у этих технологий общего – это разве что библиотеки .NET Framework. Я не буду писать тут – лучше или хуже MVC чем WebForms, просто они обе хороши, и на обеих технологиях можно построить хорошее приложение. Свои мысли по поводу необходимости TDD я тоже пока оставлю при себе, хотя их есть у меня.

А сейчас я буду говорить о стандартнейшей задаче – обычной работе с данными: просмотре в табличном виде списка записей, добавлении, изменении и удалении данных (операции CRUD). Однако практически во всех книгах и во многих решениях в интернете для ASP.NET MVC почему-то рассматривается вариант исключительно через ORM (Object Relation Mapping): или Entity Framework (EF) или LINQ для SQL. Технологии отличные, спору нет, наконец-то программист может и не разбираться – а как вообще эта самая реляционная СУБД (которой он, скорее всего, пользуется) вообще работает, и даже SQL, по идее, знать уже необязательно: прокладка в виде EF и коннектора для СУБД разберутся между собой. «Вот оно счастье – нет его краше». Но тем программистам, которые не боятся прямой работы с базой данных через механизм ADO.NET, зачастую непонятно – а с чего вообще начинать в ASP.NET MVC и надо ли.

Плюс к этому, у меня, например, вначале вызвало дикую ломку отсутствие удобного компонента для отображения данных в таблице-гриде. Подразумевается, что это всё должен реализовывать сам разработчик или брать в менеджере пакетов что-то подходящее. Если вас, как и меня, компонент GridView в ASP.NET WebForms устраивал более чем, то для MVC сложно найти что-то более-менее сопоставимое, разве что Grid.mvc. Но вот доверия у меня к подобным компонентам маловато, чтобы их использовать для достаточно крупного проекта. В случае их использования, программист начинает зависеть от другого разработчика, который, во-первых, неизвестно как написал этот компонент (качественно ли?), а, во-вторых, неизвестно когда и как будет его дорабатывать. Расширять компонент и пилить дальше иногда вроде бы даже можно, но, в случае доработки оного разработчиком, мы вынуждены либо опять перелопачивать свой код, либо замораживать обновление компонента на определенной версии. А если разработчик устранит какую-либо уязвимость – всё равно придется переходить на новую версию. Даже переход на новые версии коннектора MySQL вызывает определенные проблемы, хотя его всё-таки крупная компания разрабатывает, а что там с многочисленными «велосипедами» в менеджере пакетов Nuget?

Итак, попытаемся научиться писать под ASP.NET MVC, при этом будем работать с данными, которые обрабатываются СУБД MySQL. Весь код можно взять вот по этому адресу, ниже этот код будет частично презентован с небольшими ссылками и пояснениями. А здесь можно посмотреть на работу приложения.

Создаем базу данных в MySQL

База данных (БД) будет простая и представлена всего двумя таблицами, со одной связью «один-ко-многим» между ними по полю LanguageID . Этим я собираюсь усложнить ситуацию для необходимости использования выпадающего списка выбора одного из языков для пользователя. Также, для усложнения, для пользователя введём еще поле SupporterTier , которое будет определять уровень поддержки пользователя посредством перечисления (enum). А для того, чтобы у нас в проекте использовались почти все типы данных, добавим ещё поле LastLoginDate типа «дата/время», которое будет заполняться самим приложением при входе пользователя (в данном проекте не отражено).

Создаем проект

Выбираем «MVC». Можно и «Пустой», но у нас учебное, а не реальное приложение, поэтому это нам поможет сразу, без лишних телодвижений, интегрировать в наше приложение Bootstrap и JQuery.

Получаем уже заполненные папки Content, Fonts, Scripts, а также файлы BundleConfig.cs и FilterConfig.cs в каталоге App_Start с регистрациями связок и фильтров ASP.NET MVC. В пустом проекте там есть только регистрация маршрутов в файле RouteConfig.cs. В Global.asax.cs также добавятся вызовы методов, описанных в этих файлах:

Настраиваем инфраструктуру и всю обвязку

Для работы с СУБД MySQL добавляем библиотеку MySql.Data: либо вручную, если коннектор mysql-connector-net-8.0.18 уже установлен на компьютер, либо из менеджера пакетов Nuget:

Добавляем в файл Web.config конфигурацию строки подключения к СУБД MySQL:

Добавляем в раздел <appSettings> строку со ссылкой на добавленную строку подключения: <add key=»ConnectionString» value=»example» />
Добавляем в приложение новый каталог Domain, в нём создаем новый статический класс Base (в файле Base.cs), в котором идут обращения к этим параметрам:

Мне нравится иметь в приложении некий базовый класс со ссылками на параметры приложения и какими-нибудь стандартными функциями, которые можно было бы вызывать из всего приложения.
Название строки подключения определено в параметрах приложения, чтобы в дальнейшем было проще работать со строкой подключения к СУБД: быстро переключаться между разными базами данных и менять параметры подключения. Кроме этого, использование названия строки подключения в параметре приложения, удобно использовать для публикации приложения в Microsoft Azure – там можно задать параметр для службы приложения, которая используется для публикации, и в нём определить нужную строку подключения, которая заранее определена в <connectionStrings> . Тогда при публикации можно не использовать трансформацию файла web.config.

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

В файле-макете страницы _Layout.cshtml (стандартно располагается в каталоге Views\Shared и в дальнейшем используется для всех страниц данного проекта) можно теперь использовать эти переменные (см. например, Example_Users.Properties.Resources.Title ):

Также в этом файле видим прикрепление каскадной таблицы стилей подключенного Bootstrap и библиотеки скриптов JQuery. Содержимое всех представлений будет генерироваться в месте размещения вызова функции RenderBody() .

M — значит модель

Добавляем файл UserClass.cs в каталог Domain:

А также файл LanguageClass.cs в тот же каталог:

Тут можно видеть, что свойства классов повторяют структуру таблицы Users и Languages в СУБД. Для типа перечисления создан enum Supporter , чтобы его можно было использовать для свойства класса SupporterTier аналогичного поля таблицы БД. Для полей UserID , LanguageID можно видеть, что они заданы, как первичный ключ, точно так же, как и в БД. Для этого использован атрибут [Key] .

Все остальные атрибуты имеют отношение скорее к представлениям (view), использующим этот класс. И если мы собираемся использовать хелперы для формирования HTML-тегов для этих свойств (что я лично однозначно рекомендовал бы), то нам придется очень тщательно устанавливать эти атрибуты, чтобы получить то, что нам надо. В частности, вот то, что понадобилось для этого проекта:

  • [DisplayName] – используется как отображаемое на экран имя для класса. Иногда может быть полезно, в данном проекте специально добавил использование хелпера Html.DisplayNameForModel для демонстрации.
  • [Display] со свойством Name – используется как отображаемое на экран название свойства класса. Еще есть полезное свойство Order, позволяющее упорядочить последовательность отображения свойств класса в форме с использованием хелперов (по умолчанию сортировка по порядку определения свойств класса, поэтому в данном проекте свойство Order не использовалось).
  • [HiddenInput] со свойством DisplayValue . Используется для свойств, которые либо не надо показывать в формах и списках вообще ( DisplayValue=false , отрисовываются как теги input с типом hidden ), либо для свойств, которые всё-таки надо отображать, но в виде неизменяемого текста ( DisplayValue=true , отрисовывается как чистый текст, без тегов)
  • [ScaffoldColumn] – указывает, отображать ли поле в хелперах редактирования (например, Html.EditorForModel ). Если false – то в форме не будут отображены ни описание свойства класса, ни его значение. Тут нельзя использовать [HiddenInput(DisplayValue = false)] , потому что в этом случае значения данного свойства класса вообще не будут отображены не только в формах ввода информации, но и в табличных отображениях. В данном случае это потребовалось для свойства LastLoginDate , которое не вводится вручную, а заполняется где-то автоматически, но видеть нам его всё-таки надо.
  • [Required] – для проверки того, введено ли значение для свойства класса, с текстом сообщения об ошибке в свойстве ErrorMessage и свойством AllowEmptyStrings позволяющим вводить пустые строки.
  • [EmailAddress] – аналогичный, по сути, атрибут для проверки корректности почтового адреса.

V — значит вендетта представление

В каталоге Views создаем каталог Users для наших представлений. Все наши представления используют стандартный (определен в файле _ViewStart.cshtml в каталоге Views) макет _Layout.cshtml, расположенный в каталоге Views\Shared. Создаем представление Index (файл Index.cshtml в каталоге Users):

Если мы хотим, чтобы данное представление запускалось по умолчанию, то в файл RouteConfig.cs вносим изменение для Default :

В самом представлении надо обратить внимание на строчку с Html.Partial(«List») . Это нужно для отрисовки в данном месте специального отдельного общего частичного представления, расположенного в файле List.cshtml в каталоге Views\Shared. Собственно оно представляет из себя именно таблицу-грид для отображения данных из нашей таблицы БД users :

Читать:
Как сохранить изменения datagrid в mysql

Видно, что в заголовке таблицы данных используются хелперы Html.DisplayNameFor для отображения названий колонок и для этого приходится указывать ссылку на свойство объекта класса. Поскольку при формировании заголовка таблицы у нас есть только объект Model.Users , который представляет собой список объектов типа UserClass , то приходится применять следующий способ: выбирать первую строку этого списка, как объект класса UserClass . Например, для имени пользователя: Model.Users.First().Loginname . Поскольку у свойства Loginname класса Users указан атрибут [Display(Name = «Login»)] , то в названии колонки будет выведено именно «Login»:

Что еще интересно в представлении List ? Блок с foreach , понятно, отрисовывает объекты класса UserClass , которые находятся в списке Users , полученного из контроллера. А интересны тут объекты SortingInfo и PagingInfo в нашей модели UsersGrid . А эти объекты нужны нам для организации сортировки данных (используется в заголовке таблицы в тегах <th> ) и организации постраничного вывода информации (используется внизу страницы, под таблицей). Именно поэтому мы не используем в качестве модели чисто список объектов типа IEnumerable<UserClass> . А в качестве модели используем класс UsersGrid , который расположили в файле UsersGrid.cs в каталоге Model.

И сами классы PagingInfo и SortingInfo в файле GridInfo.cs в том же месте.

А для использования в представлениях добавлены специальные хелперы в файле GridHelpers.cs (каталог HtmlHelpers):

Поскольку грид с данными без сортировки и без постраничного вывода информации достаточно бесполезная вещь, а стандартного хелпера для целой таблицы данных в ASP.NET MVC нет, то приходится их создавать самостоятельно (либо брать созданный кем-то другим). В данном случае, я подсмотрел несколько реализаций в книгах по ASP.NET MVC и решений представленных в интернете. Причем, почему-то решений, объединяющих вместе хотя бы и сортировку данных и постраничный вывод, либо вовсе нет, либо я не нашел. Пришлось всё это дело осмысливать, объединять и дорабатывать до нормального состояния. Например, постраничный вывод в тех реализациях зачастую не предусматривает вывод более-менее длинного списка страниц – ну а вдруг будет несколько тысяч страниц? Привожу пример отображения для представленного выше решения:

Также нам потребуются представления для создания и модификации данных. Представление для создания объекта типа UserClass :

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

В этом представлении для примера показано использование хелпера Html.EditorFor в качестве средства для генерации тегов для редактирования всех свойств объектов класса UserClass . Оно отображается следующим образом:

В этом представлении используется в качестве модели класс UserModel , а не UserClass непосредственно. Сам класс UserModel размещен в файле UserModel.cs в каталоге Models:

В этот класс включен собственно сам объект UserClass и дополнительный список объектов типа LanguageClass . Этот список нам потребовался для создания выпадающего списка языков, с выбором в нём текущего языка пользователя: @Html.DropDownListFor(m => Model.User.Language.LanguageID, Model.SelectLanguages(), «»)

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

Для генерации выпадающего списка нам приходится использовать отдельные хелперы, потому что хелпер Html.EditorFor(m => m.User) не будет генерировать разметку редактирования для вложенного объекта типа LanguageClass (это можно было бы обойти написав общий шаблон для выпадающих списков, но тут мы это делать не будем…).

И поскольку у нас в представлении используется объект класса UserModel , который включает в себя еще один объект класса UserClass , то и использовать хелпер Html.EditorForModel() не удастся, поскольку хелперы не являются рекурсивными и не будут работать в данной ситуации, поэтому используется хелпер Html.EditorFor() для объекта User .

Также хочется обратить внимание на закомментированный тэг: Html.ActionLink(«Back to list», «Index»)

Обычно подобным образом реализуется возврат из представления для редактирования обратно в список данных. На самом деле, во-первых, на мой взгляд, это смотрится странно – когда в форме у тебя используются кнопки типа button , а кнопка возврата почему-то реализована ссылкой. Во-вторых, если мы будем использовать сортировку и постраничный вывод – придется мудрить с возвратом в тот же вид на ту же страницу – и передавать в представление не только объект UserClass , но и параметры для возврата обратно на страницу. Есть гораздо более простой способ – воспользоваться вариантом с кнопкой вида: /> , которая и отправит пользователя обратно на страницу по истории браузера. Тут, безусловно, есть нюансы (например, вы уже на этой странице пытались сохранить объект, не получилось, и вот – вам уже надо дважды щелкать кнопку отмены), но данный вариант в целом неплохо работает.

И представление для редактирования объекта типа UserClass :

А в этом представлении представлен вариант использования разных хелперов для генерации тегов отдельно для каждого нужного свойства объекта класса. В данном случае можно уже сделать отображение в несколько другом – более симпатичном виде:

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

И тут еще возник нюанс, связанный с использованием свойства класса типа enum. Дело в том, что если мы просто будем использовать хелпер Html.EditorFor() , то на форме отобразится поле ввода текстовой информации (тег вида <input type=”text”/> ), а нам вообще-то нужно поле с выбором из набора значений (т.е. тег <select> с набором опций <option> ).

1. Прямолинейно это решается использованием хелпера типа Html.DropDownListFor() или Html.ListBoxFor() , например, в нашем случае: @Html.DropDownListFor(m => m.Model.User.SupporterTier, new SelectList(Enum.GetNames(typeof(Example_Users.Domain.Supporter)))) . Тут два минуса – каждый раз это придется прописывать индивидуально и для хелпера Html.EditorForModel() или Html.EditorFor() это не подойдет.

2. Можно создать пользовательский шаблон типа Editor . Создаем файл Supporter.cshtml в папке Views\Shared\EditorTemplates:

Название файла должно соответствовать названию типа, либо придется писать не Html.EditorFor(m => Model.SupporterTier) , а Html.EditorFor(m => Model.SupporterTier, «Supporter») . Если файл назвать по-другому, то перед описанием свойства в классе надо будет добавить подсказку [UIHint(«Supporter»)] . И это также придется делать, если планируется использовать Html.EditorForModel() – для него решение вида Html.EditorFor(m => Model.SupporterTier, «Supporter») не подойдет.

Мне этот вариант не подошел из-за того что, при попытке создания пользователя (запуск представления New ) программа для хелперов Html.EditorFor() и Html.EditorForModel() выпадала с ошибкой: «Элемент модели, переданный в словарь, имеет значение NULL, но для этого словаря требуется элемент модели типа «Example_Users.Domain.Supporter», не имеющий значение NULL.» Причина понятна – значение для перечисления не может быть пустым, но решить проблему так и не удалось. Поэтому стал разбираться дальше.

3. Можно использовать хелпер Html.EnumDropDownListFor() , специально сделанный для перечислений. Вот тут всё хорошо, ничего дополнительно писать не нужно, отображается всё корректно, работает и при редактировании и при создании объекта. Кроме одного «но»: хелпер Html.EditorForModel() использует для отображения всех свойств хелперы Html.EditorFor() и, соответственно, не использует Html.EnumDropDownListFor() . И, как я понял, это нельзя обойти с помощью атрибутов для свойств класса – [UIHint] , [DataType] и [EnumDataType] тут не сработают. Также не будут работать атрибуты для значений перечисления, то есть вместо None не получится, например, вывести пустую строку, как это определено в описании перечисления Supporter .

4. В итоге, мне подошел вариант решения, найденный на просторах интернета: создание общего шаблона для перечислений. Создаем файл Enum.cshtml в папке Views\Shared\EditorTemplates:

Вот тут всё вообще хорошо получилось: шаблон замечательно работает везде, где только можно. Даже [UIHint(«Enum»)] можно не добавлять. Причем данный общий шаблон читает атрибут [Display(Name)] для значений перечислений с помощью специальной функции.

C — значит контроллер

Добавляем файл UsersController.cs в каталог Controllers.

Разберём методы контроллера:

Отображение страницы со списком пользователей: public ViewResult Index(string sortOrder, int page = 1)

Тут два входных параметра sortOrder и page . С page всё более-менее понятно, а вот через sortOrder из адресной строки можно передать произвольную строку, которую нам потом придется запихивать в SQL-запрос и делать это напрямую нельзя. Поэтому разбираем эту строку с помощью функции (здесь приводить саму функцию не буду, можно посмотреть в файле Base.cs): sortOrder = Base.parseSortForDB(sortOrder, out sortName, out sortDir);

Далее всё банально, создаем объект репозитария UsersRepository (для работы с СУБД, разобран в следующей главе), вызываем метод List для получения списка пользователей и формируем объект класса UsersGrid из собственно полученного списка пользователей и информации необходимой для организации постраничного вывода информации и сортировки. Причём значение totalItem получаем при вызове метода List , одновременно с созданием объекта класса UsersGrid . Далее этот объект передается для отображения представлению.

Также есть другой метод Index с атрибутом [HttpPost] , который нам потребовался для отработки нажатия кнопки New в представлении Index : public ActionResult Index(string onNewUser)

Входной параметр onNewUser перекликается с элементом /> в представлении Index и при клике на этой кнопке передает в функцию значение, которое мы сверяем с null. Если бы кнопок типа submit было бы в представлении Index несколько, пришлось бы проверять и само значение (в данном случае значение было бы «New user»).

После проверки мы формируем объект класса UserModel , состоящий из нового объекта UserClass и списка языков для выбора их из выпадающего списка и передаем его представлению New . Список языков получается из репозитария LanguageRepository вызовом метода List следующим образом:

Метод New без параметра сделан для отработки клика по ссылке New User для закомментированой строки Html.ActionLink(«New user», «New», «Users») в представлении Index . Действие (открытие представления New ) осуществляется аналогично предыдущему, только проверки на нажатую кнопку нет, потому что отрабатывается нажатие на ссылку.

Метод New с параметром model типа UserModel для отработки события отправки данных формы с целью сохранения нового пользователя в БД: public ActionResult New(UserModel model)

Получает из представления New заполненный объект класса UserModel , проверяет корректность данных (согласно требованиям, описанным в UserClass и LanguageClass ), создает объект репозитария UsersRepository и пытается добавить новую строку в БД, вызвав функцию AddUser(model.User) . Потом осуществляется возврат на предыдущую страницу (откуда был вызов представления New ) и там отображается сообщение об успехе операции или о неудаче.

Метод Edit с входным параметром UserID (идентификатор пользователя) отрабатывает щелчок по имени пользователя в списке для открытия представления редактирования данных пользователя: public ActionResult Edit(int UserID)

В методе опять же создается репозитарий UsersRepository и из него вызывается функция FetchByID(UserID) для получения объекта типа UserClass . В случае удачи создается модель – объект класса UserModel из полученного объекта и списка языков и передается в представление Edit для отображения.

Метод с входным параметром модели типа UserModel и строки action : public ActionResult Edit(UserModel model, string action)

В данный метод передается объект типа UserModel и он отрабатывает действия при нажатии на кнопки (отработка событий отправки данных формы) представления Edit . Для того чтобы понять, какая кнопка нажата используется входной параметр action , который указан в имени HTML-тегов типа input . Поэтому в методе идет сравнение значения данного параметра со значениями параметра value этих кнопок. До проверки модели на валидность проверяется значение Cancel , для выполнения действий по отмене редактирования пользователя. Этот вариант используется вместо возврата назад по истории браузера, примененный в представлении New и использующий запоминание адреса страницы, с которой перешли к представлению Edit . Для этого в контроллере продемонстрирована технология использования своего атрибута ActionFilter : класс ReferrerHoldAttribute в файле ReferrerHoldAttribute.cs (каталог HtmlAttribute):

Он используется для хранения информации о той странице, куда надо вернуться после нажатия кнопки «New user» или ссылки на изменение пользователя: TempData[«referrer»] = ControllerContext.RouteData.Values[«referrer»];

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

В дальнейшем, в теле метода, обрабатывающего действия представлений New и Edit , извлекается запомненная информация и используется для переадресации обратно на страницу, откуда были вызваны эти представления: if (TempData[«referrer»] != null) return Redirect(TempData[«referrer»].ToString());

Для определения необходимости сохранения или удаления пользователя происходит сравнение параметра action со значениями Save и Remove соответственно, и вызываются из репозитария UsersRepository функции ChangeUser(model.User) и RemoveUser(model.User) . Потом происходит возврат на предыдущую страницу (откуда был вызов представления Edit ) и там отображается сообщение об успехе операции или о неудаче.

ADO.NET и MySQL – репозитарий

Вот тут мы наконец-то добрались до работы с СУБД. Нам надо реализовать функции добавления пользователя в таблицу Users , внесение изменений в данные пользователя, удаление пользователя из таблицы, получения пользователя по идентификатору, получения списка пользователей и получения списка языков из таблицы Languages .

В основном используются стандартные конструкции для класса MySQL.Data с использованием MySqlCommand :

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

Создаем файл UserRepository.cs в каталоге Models:

Он содержит метод AddUser для добавления пользователя, обновления данных пользователя ( ChangeUser ), удаления ( RemoveUser ), поиска пользователя ( FetchByID ) по идентификатору и наиболее интересный метод List для вывода постраничного списка пользователей с сортировкой. Хотелось бы дополнительно прокомментировать функцию List :

  1. Не стоит возвращать именно таблицу ( DataTable ), как таковую – в этом случае мы потеряем в представлении возможность обращаться к элементам класса и будем вынуждены употреблять строковые константы для обращения к значениям в строке таблицы. Т.е. это будет потенциальное место для возникновения ошибок при изменении SQL-запроса. Поэтому создается список из элементов класса UserClass .
  2. Для добавления ограничения выборки строк из запроса используется конструкция LIMIT в SQL-операторе SELECT . К сожалению, в MySQL не поддерживаются переменные в этой части, и конструкцию LIMIT приходится конструировать вручную и добавлять к запросу. Но это полбеды, поскольку там используются целочисленные значения, а вот подобная практика для конструкции ORDER BY уже чревата нюансами в части инъекции в наш запрос вредоносного кода. Например, злоумышленник может подсунуть в качестве параметра сортировки некий SQL-конструкт, который прервет нашу команду SQL точкой с запятой, а дальше будет идти уже его команда, которая также может быть выполнена. Необходима проверка и чистка входного параметра сортировки, которая у нас осуществляется в контроллере, поэтому в данном методе мы принимаем уже два разобранных значения: название столбца по которому идёт сортировка и направление сортировки.
  3. После получения списка из БД мы должны запустить ещё команду SQL вида SELECT FOUND_ROWS() , которая должна нам дать общее количество строк получаемых предыдущим запросом, в котором была конструкция SELECT SQL_CALC_FOUND_ROWS без учета ограничения в LIMIT .

И файл LanguageRepository.cs в каталоге Models:

В нём есть только одна функция для получения списка языков из БД, создающая список из элементов класса LanguageClass .

Похожие статьи