简体   繁体   English

无法使用Dapper和作为@变量传入的数据库名称创建数据库,为什么?

[英]Cannot create database using Dapper and database name passed in as @ variable, why?

I have a code to create database with dapper: 我有一个代码用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");

Every time I run this method, I get an error: 每次运行此方法时,都会出现错误:

Incorrect syntax near '('. '('附近的语法不正确。

With trace: 带痕迹:

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

If I set the query the ugly way 如果我以丑陋的方式设置查询

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

and run 并运行

connection.Execute(DATABASE_CREATE_QUERY);

it all works fine. 一切正常。

If I don't use the brackets () in the QUERY 如果我不使用QUERY中的方括号()

const string DATABASE_CREATE_QUERY = "CREATE DATABASE @databaseName";

I get an error: 我收到一个错误:

Incorrect syntax near '@databaseName' '@databaseName'附近的语法不正确

I have also tried methods ExecuteScalar, Query, but with the same result. 我也尝试过ExecuteScalar,Query方法,但结果相同。

Any ideas why this wont work the Dapper way? 任何想法为什么这将无法使用Dapper方式?

This is because sp_executesql is being used for parameterizing.This is what is being executed in the database via Dapper interpretation; 这是因为使用sp_executesql进行参数设置。这是通过Dapper解释在数据库中执行的;

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

See why that wont work with sp_executesql: Table name as variable 请参阅为什么它不能与sp_executesql一起使用: 表名作为变量

Your best bet would be to either create a stored procedure, or use the approach of string replacement. 最好的选择是创建一个存储过程,或使用字符串替换方法。

Because create database statement doesn't require (). 因为create database语句不需要()。

Try : 尝试:

const string DATABASE_CREATE_QUERY = "CREATE DATABASE @databaseName";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM