Не удается создать базу данных, используя Dapper и имя базы данных, переданное как переменная @, почему? - PullRequest
0 голосов
/ 04 октября 2018

У меня есть код для создания базы данных с dapper:

public static bool CreateDatabase(string connectionString, string databaseName)
{
    const string DATABASE_CREATE_QUERY = "CREATE DATABASE (@databaseName)";

    using (var connection = new SqlConnection(connectionString))
    {
        var affectedRows = connection.Execute(DATABASE_CREATE_QUERY, new { databaseName });

        return affectedRows > 0 ? true : false;
    }
}

CreateDatabase("Server=10.10.10.10;User ID=user;Password=password;MultipleActiveResultSets=true;", "TEST_DB");

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

Неверный синтаксис рядом с '('.

С трассировкой:

at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, CommandDefinition& command, Action`2 paramReader) in E:\GitHub\Dapper\Dapper\SqlMapper.cs:line 2827
at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition& command) in E:\GitHub\Dapper\Dapper\SqlMapper.cs:line 570
at Dapper.SqlMapper.Execute(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable`1 commandTimeout, Nullable`1 commandType) in E:\GitHub\Dapper\Dapper\SqlMapper.cs:line 443
at DbCreator.DbUtils.CreateDatabase(String connectionString, String databaseName) in E:\src_projects\DbCreator\DbUtils.cs:line 48
at DbCreator.***.Run(String connectionString) in E:\src_projects\DbCreator\***.cs:line 23

Если я задам запрос безобразным образом

const string DATABASE_CREATE_QUERY = $"CREATE DATABASE {databaseName}";

и запусту

connection.Execute(DATABASE_CREATE_QUERY);

itвсе работает нормально.

Если я не использую скобки () в QUERY

const string DATABASE_CREATE_QUERY = "CREATE DATABASE @databaseName";

Я получаю ошибку:

Неправильный синтаксис рядом с '@ databaseName '

Я также пробовал методы ExecuteScalar, Query, но с тем же результатом.

Есть идеи, почему это не сработает по Дапперу?

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Это потому, что sp_executesql используется для параметризации. Это то, что выполняется в базе данных через интерпретацию Dapper;

exec sp_executesql N'Create Database (@DBName)',N'@DBName nvarchar(4000)',@DBName=N'Test'

Узнайте, почему это не будет работать с sp_executesql: Имя таблицы в качестве переменной

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

0 голосов
/ 04 октября 2018

Поскольку оператор создания базы данных не требует ().

Попробуйте:

const string DATABASE_CREATE_QUERY = "CREATE DATABASE @databaseName";
...