由于SQL Azure不支持USE [dbname]
,我试图通过在连接字符串中指定数据库名称然后执行CREATE TABLE...
脚本来连接到我的SQL Azure数据库。但是,这会因System.Data.SqlClient.SqlException “在数据库'master'中拒绝CREATE TABLE权限而失败。”我在这里做错了,它试图对master执行此语句?
以下是C#代码示例:
string connectionString = @"Data Source=tcp:MYSERVER.database.windows.net;Initial Catalog=MYDATABASE;Integrated Security=False;User ID=USER@MYSERVER;Password=PWD;Connect Timeout=60;Encrypt=True;TrustServerCertificate=True";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
ServerConnection serverConnection = new ServerConnection(connection);
Server server = new Server(serverConnection);
server.ConnectionContext.ExecuteNonQuery("CREATE TABLE New (NewId int)");
}
答案 0 :(得分:8)
事实证明我的代码存在多个问题。在SQL Azure中,SMO仍然很古怪。所以,发布我的调查结果,以防有人正在经历同样的艰难道路。
Database database = server.Databases[databaseName]
初始目录成为Master,您可以在 server.ConnectionContext.ConnectionString (“普通”SQL不执行此操作)中更改的连接字符串中看到它。对此的解决方案是每次将数据库切换到Master时打开一个新连接(并关闭旧连接),因为一旦建立连接就无法更改数据库名称(显然,只有SQL Azure才能这样做)。
所以最终的代码片段看起来像这样:
string connectionString = "Server=tcp:XXXXX.database.windows.net;Database=XXXXXX;User ID=XXXXXX;Password=XXXXX;Trusted_Connection=False;Encrypt=True;trustservercertificate=true";
SqlConnection connection = new SqlConnection(connectionString);
// do not explicitly open connection, it will be opened when Server is initialized
// connection.Open();
ServerConnection serverConnection = new ServerConnection(connection);
Server server = new Server(serverConnection);
// after this line, the default database will be switched to Master
Database database = server.Databases["MyDatabase"];
// you can still use this database object and server connection to
// do certain things against this database, like adding database roles
// and users
DatabaseRole role = new DatabaseRole(database, "NewRole");
role.Create();
// if you want to execute a script against this database, you have to open
// another connection and re-initiliaze the server object
server.ConnectionContext.Disconnect();
connection = new SqlConnection(connectionString);
serverConnection = new ServerConnection(connection);
server = new Server(serverConnection);
server.ConnectionContext.ExecuteNonQuery("CREATE TABLE New (NewId int)");
如果有人感兴趣,这里是第2点的模糊例外:
Microsoft.SqlServer.Management.Common.ConnectionFailureException was unhandled
Message=Failed to connect to server .
Source=Microsoft.SqlServer.Smo
StackTrace:
at Microsoft.SqlServer.Management.Smo.DatabaseCollection.get_Item(String name)
InnerException: System.Data.SqlClient.SqlException
Message=Login failed for user 'XXXXXXXX'.
This session has been assigned a tracing ID of 'XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX'. Provide this tracing ID to customer support when you need assistance.
Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=14
LineNumber=65536
Number=18456
Procedure=""
Server=tcp:XXXXXXXX.database.windows.net
State=1
StackTrace:
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK)
at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject)
at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at Microsoft.SqlServer.Management.Common.ConnectionManager.InternalConnect(WindowsIdentity impersonatedIdentity)
at Microsoft.SqlServer.Management.Common.ConnectionManager.Connect()
答案 1 :(得分:0)
只是一个疯狂的猜测,基于一个恰好适合我的连接字符串。
您是否尝试过使用
数据库= MYDATABASE
取代
连接字符串中的初始目录= MYDATABASE
?
答案 2 :(得分:0)
还有一件事有助于我 - 应该为每个操作断开ServerConnection。
using (var connection = new SqlConnection(parameters.ConnectionStringToMasterDatabase))
{
var serverConnection = new ServerConnection(connection);
try
{
var server = new Server(serverConnection);
// do something
}
finally
{
serverConnection.Disconnect();
}
}
using (var connection = new SqlConnection(parameters.ConnectionStringToMasterDatabase))
{
var serverConnection = new ServerConnection(connection);
try
{
var server = new Server(serverConnection);
// do something else
}
finally
{
serverConnection.Disconnect();
}
}