Запрос к базе данных с помощью ExecuteScalar (): необходимо объявить табличную переменную "@tableName" - PullRequest
0 голосов
/ 13 февраля 2020

Я пытаюсь вернуть значения из столбца таблицы в базе данных, используя ExecuteScalar().

Программное обеспечение выдает исключение при ExecuteScalar(), заявляя Must declare the table variable "@tableName".

Однако @tableName объявлено, поэтому я не уверен, почему я получаю эту ошибку.

Код:

public object GetListOfDatabases(string tableName)
        {
            switch (tableName)
            {
                case "PMS":
                    tableName = "CALCULATION_SCHEDULE";
                    break;
                case "UKPMS":
                    tableName = "UKPMS_CALCULATION_SCHEDULE";
                    break;
                case "RCI":
                    tableName = "RCI_CALCULATION_SCHEDULE";
                    break;
            }

            if(tableName != null)
            {
                var connection = calculationContext.Database.GetDbConnection();

                if (connection.State.Equals(ConnectionState.Closed))
                    connection.Open();

                using (var command = connection.CreateCommand())
                {
                    command.CommandText = @"
                    SELECT DATABASE_NAME FROM @tableName 
                    ";

                    var tableNameParam = command.CreateParameter();
                    tableNameParam.ParameterName = "@tableName";
                    tableNameParam.Value = tableName;
                    command.Parameters.Add(tableNameParam);
                    return command.ExecuteScalar();
                }
            }
            else
            {
                return null;
            }
}

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

public bool tableExists(string schema, string tableName)
        {
            var connection = calculationContext.Database.GetDbConnection();

            if (connection.State.Equals(ConnectionState.Closed))
                connection.Open();

            using (var command = connection.CreateCommand())
            {
                command.CommandText = @"
                    SELECT 1 FROM INFORMATION_SCHEMA.TABLES 
                    WHERE TABLE_SCHEMA = @Schema
                    AND TABLE_NAME = @TableName";

                var schemaParam = command.CreateParameter();
                schemaParam.ParameterName = "@Schema";
                schemaParam.Value = schema;
                command.Parameters.Add(schemaParam);

                var tableNameParam = command.CreateParameter();
                tableNameParam.ParameterName = "@TableName";
                tableNameParam.Value = tableName;
                command.Parameters.Add(tableNameParam);

                return command.ExecuteScalar() != null;
            }
        }

1 Ответ

1 голос
/ 13 февраля 2020

Имена таблиц не могут быть параметризованы.

Вы должны будете решить эту проблему путем интерполяции строк или аналогичным образом:

command.CommandText = $@"SELECT DATABASE_NAME FROM {tableName}";

Конечно, это открывает ваш запрос для инъекции SQL, поэтому вам нужно занести в белый список имена таблиц.

Может быть, с помощью исключения:

switch (tableName)
{
    case "PMS":
        tableName = "CALCULATION_SCHEDULE";
        break;
    case "UKPMS":
        tableName = "UKPMS_CALCULATION_SCHEDULE";
        break;
    case "RCI":
        tableName = "RCI_CALCULATION_SCHEDULE";
        break;
    default:
        throw new ArgumentException("Invalid table");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...