Язык программирования C#9 и платформа .NET5
В реальной программе была бы предусмотрена логика обработки такой ошибки, но в рассматриваемом примере просто генерируется новое исключение. Добавьте в класс
следующий метод:InventoryDalpublic void DeleteCar(int id){OpenConnection();// Получить идентификатор автомобиля, подлежащего удалению,// и удалить запись о нем.string sql = $"Delete from Inventory where Id = '{id}'";using (SqlCommand command = new SqlCommand(sql, _sqlConnection)){try{command.CommandType = CommandType.Text;command.ExecuteNonQuery();}catch (SqlException ex){Exception error = new Exception("Sorry! That car is on order!", ex);throw error;}}CloseConnection();}Добавление логики обновления
Когда речь идет об обновлении существующей записи в таблице
, первым делом потребуется решить, какие характеристики будет позволено изменять вызывающему коду: цвет автомобиля, его дружественное имя, модель или все перечисленное? Один из способов предоставления вызывающему коду полной гибкости заключается в определении метода, принимающего параметр типаInventory, который представляет любой оператор SQL, но в лучшем случае это сопряжено с риском.stringВ идеале лучше иметь набор методов, которые позволяют вызывающему коду обновлять запись разнообразными способами. Тем не менее, определите для такой простой библиотеки доступа к данным единственный метод, который дает вызывающему коду возможность обновить дружественное имя указанного автомобиля:
public void UpdateCarPetName(int id, string newPetName){OpenConnection();// Получить идентификатор автомобиля для модификации дружественного имени.string sql = $"Update Inventory Set PetName = '{newPetName}'Where Id = '{id}'";using (SqlCommand command = new SqlCommand(sql, _sqlConnection)){command.ExecuteNonQuery();}CloseConnection();}Работа с параметризированным и объектами команд
В настоящий момент внутри логики вставки, обновления и удаления для типа
используются жестко закодированные строковые литералы, представляющие каждый запрос SQL. В параметризированных запросах параметры SQL являются объектами, а не простыми порциями текста. Трактовка запросов SQL в более объектно-ориентированной манере помогает сократить количество опечаток (учитывая, что свойства строго типизированы). Вдобавок параметризированные запросы обычно выполняются значительно быстрее запросов в виде строковых литералов, т.к. они подвергаются разбору только однажды (а не каждый раз, когда строка с запросом SQL присваивается свойствуInventoryDal). Параметризированные запросы также содействуют в защите против атак внедрением в SQL (хорошо известная проблема безопасности доступа к данным).CommandTextДля поддержки параметризированных запросов объекты команд ADO.NET содержат коллекцию индивидуальных объектов параметров. По умолчанию коллекция пуста, но в нее можно вставить любое количество объектов параметров, которые отображаются на параметры-заполнители в запросе SQL. Чтобы ассоциировать параметр внутри запроса SQL с членом коллекции параметров в объекте команды, параметр запроса SQL необходимо снабдить префиксом в виде символа
(во всяком случае, когда применяется Microsoft SQL Server; не все СУБД поддерживают такую систему обозначений).@Указание параметров с использованием типа DbParameter
Перед построением параметризированного запроса вы должны ознакомиться с типом
(который является базовым классом для объекта параметра поставщика). КлассDbParameterподдерживает несколько свойств, которые позволяют конфигурировать имя, размер и тип параметра, а также другие характеристики, включая направление движения параметра. Некоторые основные свойства типаDbParameterописаны в табл. 21.6.DbParameterДавайте теперь посмотрим, как заполнять коллекцию совместимых с
объектов, содержащуюся в объекте команды, для чего переделаем методыDBParameterдля использования параметров.InventoryDalОбновление метода GetCar()
В исходной реализации метода
при построении строки SQL для извлечения данных об автомобиле применяется интерполяция строк С#. Чтобы обновить методGetCar(), создайте экземплярGetCar()с соответствующими значениями:SqlParameterSqlParameter param = new SqlParameter{ParameterName = "@carId",Value = id,SqlDbType = SqlDbType.Int,Direction = ParameterDirection.Input}Значение
должно совпадать с именем, используемым в запросе SQL (который будет модифицирован следующим), тип обязан соответствовать типу столбца базы данных, а направление зависит от того, применяется параметр для отправки данных в запрос (ParameterName) или он предназначен для возвращения данных из запроса (ParameterDirection.Input). Параметры также могут определяться какParameterDirection.OutputилиInputOutput(возвращаемое значение, например, из хранимой процедуры).ReturnValue
