SQL-запрос должен объявлять скалярную переменную

У меня есть файл класса, в котором я объявляю readonly string моего запроса для использования в методе. Я встретил ошибку

Необходимо объявить скалярную переменную "@DBID"

Могу ли я узнать, неправильно ли я объявляю свои переменные?

Ниже приведены фрагменты кода:


Файл класса:

private static readonly string QUERY_GETMATCHEDRECORD = "SELECT [Title], [ItemLink], [RecordDocID] FROM [ERMS].[dbo].[Records] WHERE [ID] = @DBID AND [V1RecordID] = @recID AND [V1RecordDocID] = @recDocID";

public DataTable GetMatchedRecord(string DBID, string recID, string recDocID)
{
    string Method = System.Reflection.MethodBase.GetCurrentMethod().Name;
    DataTable dt = new DataTable();
    try
    {
        using (DB db = new DB(_datasource, _initialCatalog))
        {
            db.OpenConnection();
            using (SqlCommand command = new SqlCommand())
            {
                string commandText = QUERY_GETMATCHEDRECORD .FormatWith(DBID,recID,recDocID);
                _log.LogDebug(Method, "Command|{0}".FormatWith(commandText));
                command.CommandText = commandText;
                dt = db.ExecuteDataTable(command);
            }
            db.CloseConnection();
        }
    }
    catch (Exception ex)
    {
        _log.LogError(Method, "Error while retrieving matching records |{0}".FormatWith(ex.Message));
        _log.LogError(ex);
    }
    return dt;
}

Программный файл .cs:

MatchedRecords = oDB.GetMatchedRecord(DBID, RecID, RecDocID);

person gymcode    schedule 11.06.2019    source источник
comment
Как выглядит строка в _log.LogDebug? Разве ваша константа не должна больше походить на WHERE [ID] = {0} AND [V1RecordID] = {1} AND [V1RecordDocID] = {2}?   -  person Rafalon    schedule 11.06.2019
comment
Он зарегистрировал сообщение об ошибке и обнаруженный метод: GetMatchedRecord | Error while retrieving matched record | Must declare the scalar variable "@DBID". .Net SqlClient Data Provider | Must declare the scalar variable "@DBID"   -  person gymcode    schedule 11.06.2019
comment
Где вы устанавливаете свои переменные? FormatWith заменяет {0}, {1} и т. д. (при условии, что вы используете метод расширения Джеймса Ньютона-Кингса).   -  person HoneyBadger    schedule 11.06.2019
comment
Спасибо! Я дам ему попробовать   -  person gymcode    schedule 11.06.2019
comment
Кстати, вам действительно следует использовать параметризацию   -  person HoneyBadger    schedule 11.06.2019
comment
@gymcode, я говорил об этой строке _log.LogDebug(Method, "Command|{0}".FormatWith(commandText));, а не о той, что в блоке catch   -  person Rafalon    schedule 11.06.2019
comment
@gymcode ошибка жалуется, что вы пытались использовать переменную или параметр, но никогда не объявляли идентификатор. Что бы ни делал FormatWith, он не добавляет параметры к команде. Скорее всего, он ломает запрос, пытаясь (и терпя неудачу) заменить заполнители строками. Вот как происходят атаки SQL-инъекций. Представьте, что произойдет, если RecDocID будет содержать 1; drop table records;--. Цитирование тоже не помогает, 1'; drop table records;-- все равно сработает   -  person Panagiotis Kanavos    schedule 11.06.2019
comment
Было бы здорово, если бы вы могли предоставить минимально воспроизводимый пример. Кроме того, каково точное значение commandText?   -  person mjwills    schedule 11.06.2019
comment
@gymcode, если вы хотите упростить свой код, используйте microORM, например Dapper. Создание псевдонимов, таких как FormatWith, для общих функций, таких как String.Format, не помогает. Вы экономите 4 символа и получаете код, который никто другой не может понять. Вы можете использовать интерполяцию строк вместо FormatWith, чтобы упростить создание строк.   -  person Panagiotis Kanavos    schedule 11.06.2019


Ответы (1)


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

попробуйте следующее:

    using (DB db = new DB(_datasource, _initialCatalog))
    {
        db.OpenConnection();
        using (SqlCommand command = new SqlCommand())
        {
            command.CommandText = QUERY_GETMATCHEDRECORD;
            command.Parameters.AddWithValue("@DBID", DBID);
            command.Parameters.AddWithValue("@recID", recID);
            command.Parameters.AddWithValue("@recDocID",recDocID);
            dt = db.ExecuteDataTable(command);
        }
        db.CloseConnection();
    }
person Sancho Panza    schedule 11.06.2019
comment
За исключением того, что вы не должны использовать Добавить со значением - person HoneyBadger; 11.06.2019
comment
: D Я действительно не думаю, что это имеет какое-либо отношение к ОП на данном этапе его кода. Тем не менее верное замечание! Поскольку фактические типы не могут быть выведены с учетом фрагмента кода OP, я не буду редактировать свой ответ. - person Sancho Panza; 11.06.2019