Оказывается, было много проблем с кодом, который у меня был.SMO все еще довольно дурацкий, когда дело доходит до SQL Azure.Итак, публикуя мои выводы на случай, если кто-то идет по той же каменистой дороге.
- SMO переключает базу данных по умолчанию за кулисы каждый раз, когда вы получаете объект базы данных, подобный этому:
Database database = server.Databases[databaseName]
Первоначальный каталог становится Masterи вы можете увидеть это в строке подключения, которая изменяется в server.ConnectionContext.ConnectionString («нормальный» SQL этого не делает).Для этого было разрешено открывать новое соединение (и закрывать старое) каждый раз, когда база данных переключается на Master, так как имя базы данных не может быть изменено после установления соединения (очевидно, только SQL Azure может это сделать). - Открытие соединения, при котором инициализируются ServerConnection и Server, иногда может завершиться неудачей в связи с первой проблемой.Это может привести к неясному сообщению об ошибке, в котором будет указано, что при входе в систему произошел сбой, а также указание времени и отметки о времени обращения в службу поддержки.Ерунда.Решением этой проблемы было , а не , чтобы открыть соединение и позволить ServerConnection открыть его во время инициализации объекта Server:
- Наконец, Alter () не нравится SQL Azure для объекта Server.Убрал всех Алтеров.
Итак, окончательный фрагмент кода выглядит примерно так:
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()