SelectCommand с параметрами дает пустой результат

В настоящее время я немного почищу свой код, и VS сказал мне, что лучше использовать SqlParameter для команд sql вместо составного string. Поэтому я решил изменить свой код, к сожалению, теперь я не получаю результат, и я не знаю, почему. Вот кусок моего кода:

...    
DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection(GetSQLConnectionString());
SqlDataAdapter sqlSelect = new SqlDataAdapter();
try
{
    connection.Open();
    sqlSelect.SelectCommand = connection.CreateCommand();
    sqlSelect.SelectCommand.CommandText = "SELECT id, @FROM AS \"from\", @TO AS \"to\" FROM Dictionary WHERE @FROM LIKE @SEARCHSTRING";
    sqlSelect.SelectCommand.Parameters.Add(new SqlParameter("@FROM", this.from));
    sqlSelect.SelectCommand.Parameters.Add(new SqlParameter("@TO", this.to));
    sqlSelect.SelectCommand.Parameters.Add(new SqlParameter("@SEARCHSTRING", "'%" + this.SearchField.Text + "%'"));

    sqlSelect.Fill(dt);
    connection.Close();
}
catch(SqlException e)
...

Я не получаю никаких исключений. Почему dt пуст после поиска? (С составной строкой выбор работает.) Что пошло не так?

Гретц


person Andre Hofmeister    schedule 27.10.2011    source источник
comment
добавьте свою составную строку, которая сработала   -  person Renatas M.    schedule 27.10.2011
comment
вы не можете передать имя столбца в качестве параметра   -  person Lucas_Santos    schedule 27.10.2011
comment
Способ SqlParameter намного чище, мне это нравится. Было бы интересно, почему мой код не работает. @Lucas_Santos Я изменил его на имя столбца, но dt все еще пусто. Гретц   -  person Andre Hofmeister    schedule 27.10.2011


Ответы (3)


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

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

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

Если вам ДЕЙСТВИТЕЛЬНО нужно передать имена полей, которые будут использоваться в операторе select, подобном этому, вы можете сделать это в SQL и создать строку запроса, а затем выполнить ее с помощью sp_executesql.

По сути, вы объявляете строку запроса, например

DECLARE @queryString VARCHAR(3000)

SET @queryString ='SELECT id, '+@FROM+' AS from, '+@TO+' AS to FROM Dictionary WHERE +'@FROM+' LIKE %'+@SEARCHSTRING+'%'

затем просто используйте sp_executesql для выполнения @queryString

Возможно, вам придется указать параметры как Varchar, если вы получите какие-либо ошибки при создании строки запроса.

person Purplegoldfish    schedule 27.10.2011
comment
Да, мне действительно нужно передать имена полей. Конечный пользователь мог изменить выбранный столбец с помощью выпадающего списка (я знал, что это небезопасно, но я не знаю другого способа). Если я правильно вас понимаю, лучше создать процедуру, добавить в процедуру динамические поля и добавить параметры типа здесь в С#. Также для обновлений sql, удаления и т.д.? Гретц - person Andre Hofmeister; 27.10.2011
comment
Хорошо, я добавил процедуру, как вы сказали. Теперь у меня проблема, что я должен добавить «% и %» в строку поиска. В коде c# это не проблема и все работает нормально, но как я могу добавить одинарную кавычку, если я выполняю процедуру с сервера sql? В С# я делаю: cmd.Parameters["@SEARCHSTRING"].Value = "'%string%'"; . На сервере sql я выполнил exec test_ procedure @FROM = 'FROMVALUE', @TO = 'TOVALUE', @SEARCHSTRING = 'STRING'. Гретц - person Andre Hofmeister; 27.10.2011
comment
@Taz Я обновил пример, который я опубликовал, чтобы показать строку запроса с% - person Purplegoldfish; 28.10.2011
comment
Ну, это работает, но если я попытаюсь выбрать с равным (=), одинарные кавычки отсутствуют, если столбец, например, является varchar. Мне было бы интересно узнать, как я могу выполнить процедуру, которая ожидает жало на сервере sql. Собственно проблема решена. Гретц - person Andre Hofmeister; 28.10.2011
comment
@Taz, проверьте это, это довольно просто, но оно показывает, как это можно немного расширить pastebin.com/tZqQpzmW - person Purplegoldfish; 28.10.2011
comment
Ммм, во избежание недопонимания процедура работает правильно. Я хотел бы знать, как я могу выполнить процедуру с сервера sql, если параметр является строкой. Если я выполню, например, это: Procedure_Name @FROM=coumn1, @TO=coumn2, @SEARCHSTRING=SEARCHSTRING, sql-сервер скажет мне, что SEARCHSTRING не является столбцом, это правильно. Правильный синтаксис для поиска: ['SEARCHSTRING']. Спасибо всем! Грец. - person Andre Hofmeister; 28.10.2011
comment
@taz Когда вы выбираете строку, вы обычно делаете column= 'stringtext', но когда вы используете переменные, создаваемая вами строка в конечном итоге выглядит как column = stringtext без ' ', что вам нужно сделать, это убедиться, что эти символы включены в параметр, который вы передаете серверу - person Purplegoldfish; 28.10.2011

Вы не можете указать имена полей, используя такие параметры. В вашем предложении where WHERE @FROM LIKE @SEARCHSTRING он сравнивает значение параметра @FROM со значением параметра @SEARCHSTRING.

Если предложение where оценивается как true, вы получите каждую запись в таблице словаря, если оно оценивается как false, вы не получите никаких записей. Он никогда не будет рассматривать содержимое @from как имя поля в таблице словаря.

person Ben Robinson    schedule 27.10.2011
comment
Хорошо, я проверил это, и вы правы! Проблема действительно заключается в предложении where. (Параметры в позиции столбца работают нормально). Для лучшего понимания, WHERE @FROM LIKE @SEARCHSTRING сравнивая оба значения, если они совпадают, я получу полную таблицу, верно? Можно ли добавить параметр в @FROM, или мне нужно просто составить строку CommandText в этой позиции? Спасибо, привет. - person Andre Hofmeister; 27.10.2011
comment
Да, если они одинаковы, вы получите всю таблицу. Вам придется динамически создавать строку Sql, если вы хотите использовать параметры для указания имен полей. Самый безопасный способ сделать это — использовать spExecuteSql msdn.microsoft.com/en- нас/библиотека/ms188001.aspx - person Ben Robinson; 27.10.2011

Почему вы написали такой запрос?

   "SELECT id, @FROM AS \"from\", @TO AS \"to\" FROM Dictionary WHERE @FROM LIKE @SEARCHSTRING";

вы пытаетесь получить @FROM из таблицы, а также пытаетесь передать его в качестве параметра, как это должно работать? Кроме того, почему вы включили косую черту? они просто делают вещи беспорядочными, удалите их. Запрос Select принимает входные параметры только с предложением «WHERE» и больше нигде.

Попробуйте заменить на это

"SELECT id, FROM AS 'from', TO AS 'to' FROM Dictionary WHERE FROM LIKE @SEARCHSTRING";

Также удалите все, кроме последних вхождений:

sqlSelect.SelectCommand.Parameters.Add

Также позаботьтесь о том, чтобы «FROM» также было ключевым словом SQL, поэтому убедитесь, что оно интерпретируется правильно, заключив его в «[]».

Надеюсь это поможет...

person Aman    schedule 27.10.2011