2011-04-27 1 views
1

Comme USE [dbname] n'est pas pris en charge dans SQL Azure, j'essaie de me connecter à ma base de données SQL Azure en spécifiant le nom de la base de données dans la chaîne de connexion puis en exécutant le script CREATE TABLE.... Toutefois, cela échoue avec System.Data.SqlClient.SqlException "Autorisation CREATE TABLE refusée dans la base de données" maître "." Qu'est-ce que je fais de mal ici qu'il essaie d'exécuter cette déclaration contre maître?Échec de CREATE TABLE dans la base de données SQL Azure à l'aide de SMO

Voici un exemple de code C#:

 
string connectionString = @"Data Source=tcp:MYSERVER.database.windows.net;Initial Catalog=MYDATABASE;Integrated Security=False;User [email protected];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)"); }

+1

Avez-vous essayé d'utiliser SqlCommand comme indiqué dans cet exemple http://msdn.microsoft.com/en-us/library/ee336243.aspx? –

+0

Je reçois la même erreur avec SqlCommand – kateroh

Répondre

7

Il se trouve qu'il y avait plusieurs problèmes avec le code que j'avais. SMO est encore assez loufoque quand il s'agit de SQL Azure. Donc, poster mes conclusions au cas où quelqu'un traverserait la même route caillouteuse.

  1. SMO commute la base de données par défaut dans les coulisses chaque fois que vous obtenez un objet de base de données comme ceci:
    
    Database database = server.Databases[databaseName] 
    
    catalogue initial devient maître et vous pouvez le voir dans la chaîne de connexion qui change dans server.ConnectionContext.ConnectionString (SQL "normal" ne le fait pas). La résolution pour cela était d'ouvrir une nouvelle connexion (et de fermer l'ancienne) chaque fois que la base de données est passée à Master, puisque le nom de la base de données ne peut pas être changé une fois la connexion établie (apparemment, seul SQL Azure peut le faire). L'ouverture d'une connexion, avec laquelle ServerConnection et Server sont initialisés, échouera parfois en conjonction avec le premier problème.
  2. Cela donnerait un message d'erreur obscur indiquant que la connexion a échoué donnant un guid et un horodatage demandant de contacter le support client. Absurdité. La résolution de ce problème était de ne pas ouvrir la connexion et laissez ServerConnection l'ouvrir lors de l'initialisation de l'objet serveur:
  3. Enfin, Alter() n'est pas aimé par Azure SQL sur l'objet Server. Retiré tous les Alter.

Donc, l'extrait de code final ressemble à quelque chose comme ceci:


     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)"); 

Et voici l'exception obscure pour le point # 2 cas où quelqu'un est intéressé:


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

Le fait de ne pas ouvrir la connexion sql a corrigé mes erreurs de "connexion échouée pour l'utilisateur". Qui aurait su? Merci! – Nicolas

0

Juste un devinez, basé sur une chaîne de connexion qui fonctionne pour moi.

Avez-vous essayé d'utiliser

Database = myDatabase

à la place de

Initial Catalog = myDatabase

dans la chaîne de connexion?

0

Et encore une chose qui m'a aidé - ServerConnection devrait être déconnecté pour chaque opération.

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(); 
       } 
      } 
Questions connexes