c# - 无法使用 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");
每次运行此方法时,都会出现错误:
'(' 附近的语法不正确。
有迹可循:
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);
一切正常。
如果我不使用 QUERY 中的方括号 ()
const string DATABASE_CREATE_QUERY = "CREATE DATABASE @databaseName";
我收到一个错误:
“@databaseName”附近的语法不正确
我也尝试过方法 ExecuteScalar、Query,但结果相同。
任何想法为什么这不会以 Dapper 的方式工作?
解决方案
这是因为 sp_executesql 被用于参数化。这是通过 Dapper 解释在数据库中执行的;
exec sp_executesql N'Create Database (@DBName)',N'@DBName nvarchar(4000)',@DBName=N'Test'
看看为什么这不适用于 sp_executesql: Table name as variable
您最好的选择是创建一个存储过程,或者使用字符串替换的方法。
推荐阅读
- php - PHP获取日期数组,从一个长日期范围中分割出来
- ios - Angular 8 - 如何在 iOS 中下载文件
- java - 更改“bootJar”目标目录
- angular - Angular 订阅 EventEmitter 但获取现有项目
- javascript - 如何使用 jQuery 从动态加载的外部 HTML 文件中更改 CSS 属性
- sql - Oracle表中如何推进压缩分区和子分区
- git - Visual Studio 2017 和 git 中版本控制项目中的机器相关库路径
- php - 在 RabbitMQ 中是否有可能同时有一个作为消费者和生产者的回调?如果是,这是一个好方法吗?
- html - 在电话图像旁边的锚标签中显示电话链接,在信封图像旁边显示电子邮件链接
- excel - 一次强制激活一个复选框