【问题标题】:Failure to CREATE TABLE in SQL Azure database using SMO使用 SMO 在 SQL Azure 数据库中创建表失败
【发布时间】:2011-08-13 11:32:42
【问题描述】:

由于 SQL Azure 不支持 USE [dbname],我尝试通过在连接字符串中指定数据库名称然后执行 CREATE TABLE... 脚本来连接到我的 SQL Azure 数据库。但是,这失败了 System.Data.SqlClient.SqlException "CREATE TABLE permission denied in database 'master'." 我在这里做错了什么,它试图对 master 执行这个语句? p>

这是一个示例 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";

使用 (SqlConnection 连接 = 新的 SqlConnection(connectionString)) { 连接。打开(); ServerConnection serverConnection = new ServerConnection(connection); 服务器服务器 = 新服务器(服务器连接); server.ConnectionContext.ExecuteNonQuery("CREATE TABLE New (NewId int)"); }

【问题讨论】:

标签: c# smo azure-sql-database


【解决方案1】:

事实证明,我的代码存在多个问题。谈到 SQL Azure,SMO 仍然很古怪。所以,发布我的发现,以防有人走同样的坎坷道路。

  1. 每次获得这样的数据库对象时,SMO 都会在后台切换默认数据库:
    
    Database database = server.Databases[databaseName]
    
    初始目录变为主目​​录,您可以在 server.ConnectionContext.ConnectionString 中更改的连接字符串中看到它(“普通” SQL 不会这样做)。对此的解决方案是每次将数据库切换到 Master 时打开一个新连接(并关闭旧连接),因为一旦建立连接就无法更改数据库名称(显然,只有 SQL Azure 可以这样做)。
  2. 打开一个用于初始化 ServerConnection 和 Server 的连接,有时会与第一个问题一起失败。这将给出一条模糊的错误消息,指出登录失败,并提供一个 guid 和时间戳,要求联系客户支持。废话。解决这个问题的方法是打开连接,让 ServerConnection 在 Server 对象初始化期间打开它:
  3. 最后,SQL Azure on Server 对象不喜欢 Alter()。删除了所有Alter。

所以最终的代码 sn-p 看起来像这样:


       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()

【讨论】:

  • 未打开 sql 连接修复了我的“用户登录失败”错误。谁会知道?谢谢!
  • 谢谢。现在 10 年后,这个错误仍然存​​在。微软干得好。
【解决方案2】:

只是一个疯狂的猜测,基于恰好对我有用的连接字符串。

您是否尝试过使用

数据库=MYDATABASE

代替

初始目录=MYDATABASE

在连接字符串中?

【讨论】:

    【解决方案3】:

    还有一件事对我有帮助——每次操作都应该断开 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();
                    }
                }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多