无法立即连接到新创建的 SQL Server 数据库
我正在使用 SQL Server 管理对象。
我编写了以下方法来生成数据库:
public static void CreateClientDatabase(string serverName, string databaseName)
{
using (var connection = new SqlConnection(GetClientSqlConnectionString(serverName, String.Empty)))
{
var server = new Server(new ServerConnection(connection));
var clientDatabase = new Database(server, databaseName);
clientDatabase.Create();
server.ConnectionContext.Disconnect();
}
}
此后不久,我调用另一个方法来执行 SQL 脚本来生成表等:
public static void CreateClientDatabaseObjects(string createDatabaseObjectsScriptPath, string serverName, string databaseName)
{
using (var connection = new SqlConnection(GetClientSqlConnectionString(serverName, databaseName)))
{
string createDatabaseObjectsScript = new FileInfo(createDatabaseObjectsScriptPath).OpenText().ReadToEnd();
var server = new Server(new ServerConnection(connection));
server.ConnectionContext.ExecuteNonQuery(createDatabaseObjectsScript);
server.ConnectionContext.Disconnect();
}
}
语句 server.ConnectionContext.ExecuteNonQuery(createDatabaseObjectsScript)
抛出 SqlException
并显示消息无法打开登录请求的数据库“数据库名称”。登录失败。 用户“the user”登录失败。
如果我尝试单步执行调试器中的语句,则此异常永远不会发生,并且脚本执行正常。
我唯一的猜测是服务器需要一些时间来初始化数据库才能打开它。这准确吗?除了尝试连接但失败之外,是否有其他方法可以判断数据库是否已准备好?
编辑:我应该提到,在所有情况下都肯定会创建数据库。
编辑2:在创建数据库之前,我调用System.Data.Entity.Database.Exists EntityFramework.dll 方法检查数据库是否已存在。如果我删除该调用,一切似乎都会按预期进行。几乎就像该调用正在缓存结果并因查看新数据库而弄乱后续连接(无论它们是否使用实体框架)。
编辑 3:我使用 Server.Databases.Contains(databaseName)
将 EntityFramework 的 Database.Exists
方法替换为基于 SMO 的方法。我遇到同样的问题,数据库创建后无法立即打开。同样,如果我在创建之前不检查数据库是否存在,我可以在创建数据库后立即打开它,但我希望能够在创建之前检查数据库是否存在,这样我就不会尝试创建现有数据库。
EntityFramework 的Database.Exists 和SMO 的Server.Databases.Contains 都只是执行在master.sys.databases 中查找数据库名称的SQL。我不明白为什么/如何干扰数据库连接。
I'm creating a database using SQL Server Management Objects.
I wrote the following method to generate a database:
public static void CreateClientDatabase(string serverName, string databaseName)
{
using (var connection = new SqlConnection(GetClientSqlConnectionString(serverName, String.Empty)))
{
var server = new Server(new ServerConnection(connection));
var clientDatabase = new Database(server, databaseName);
clientDatabase.Create();
server.ConnectionContext.Disconnect();
}
}
Shortly thereafter, I call another method to execute a SQL script to generate tables, etc.:
public static void CreateClientDatabaseObjects(string createDatabaseObjectsScriptPath, string serverName, string databaseName)
{
using (var connection = new SqlConnection(GetClientSqlConnectionString(serverName, databaseName)))
{
string createDatabaseObjectsScript = new FileInfo(createDatabaseObjectsScriptPath).OpenText().ReadToEnd();
var server = new Server(new ServerConnection(connection));
server.ConnectionContext.ExecuteNonQuery(createDatabaseObjectsScript);
server.ConnectionContext.Disconnect();
}
}
The statement server.ConnectionContext.ExecuteNonQuery(createDatabaseObjectsScript)
throws a SqlException
with the message Cannot open database "The database name" requested by the login. The login failed.
Login failed for user 'the user'.
If I try stepping through the statements in the debugger, this exception never happens and the script executes fine.
My only guess is that the server needs some time to initialize the database before it can be opened. Is this accurate? Is there a way to tell if a database is ready other than trying and failing to connect?
Edit: I should mention that the database is definitely being created in all cases.
Edit 2: Prior to creating the database, I call the System.Data.Entity.Database.Exists method of EntityFramework.dll to check if the database already exists. If I remove that call, everything seems to work as expected. It's almost as if that call is caching the result and messing up the subsequent connections from seeing the new database (regardless of whether or not they use Entity Framework).
Edit 3: I replaced the EntityFramework's Database.Exists
method with an SMO-based approach using Server.Databases.Contains(databaseName)
. I get the same issue in that the database cannot be opened immediately after creating. Again, if I don't check if a database exists prior to creation I can immediately open it after creating it but I'd like to be able to check for existence prior to creation so I don't try to create an existing database.
Both the EntityFramework's Database.Exists
and SMO's Server.Databases.Contains
both just execute SQL that looks for the database name in master.sys.databases. I don't understand why/how this is interfering with database connections.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
刚刚上线的数据库不一定准备好接受连接。要确定数据库何时可以接受连接,请查询 sys.databases 的 collation_name 列或 DATABASEPROPERTYEX 的 Collation 属性。当数据库排序规则返回非空值时,数据库可以接受连接。
A database that has just come online is not necessarily ready to accept connections. To identify when a database can accept connections, query the collation_name column of sys.databases or the Collation property of DATABASEPROPERTYEX. The database can accept connections when the database collation returns a non-null value.
就我而言,事实证明问题不在于新创建的数据库尚未准备好。但问题是
SqlConnection.Open()
显然使用了失败的缓存连接,然后又返回了相同的错误。当我调用静态
SqlConnection.ClearAllPools()
方法在我尝试打开新创建的数据库之前,它工作正常!另请参阅此问题。
In my case it turned out that the problem is not that the newly created database is not ready. But the problem was that
SqlConnection.Open()
apparently used a failed cached connection, which then just returned the same error again.When I call the static
SqlConnection.ClearAllPools()
method before I try to open the newly created database, it works fine!See also this question.
登录请求的数据库名称。登录失败。用户“用户”登录失败
这里需要注意的一件事是错误消息与安全有关。您如何尝试登录到新数据库(即什么类型)安全性是用于新数据库连接的连接字符串)?如果您使用 SQL 身份验证,则需要发出 sp_adduser 来授予对数据库的登录访问权限
。 href="http://msdn.microsoft.com/en-us/library/ms181422.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/ms181422.aspx
The database name" requested by the login. The login failed. Login failed for user 'the user'
One thing to note here all is that the error message is surrounding security. How are you attempting to logon to the new database (i.e. what type of security is the connection string using for the new database connection)? If you are using SQL authentication you will need to issue sp_adduser to grant the login access to the database.
http://msdn.microsoft.com/en-us/library/ms181422.aspx
您必须以稍微不同的方式创建数据库。下面的代码正确处理数据库创建。试试吧;)
在下面的代码中,_connection 是
object by the way.
[编辑]
修改了代码,使异常不再被吞噬。
You have to approach the database creation a little bit different. The code below handles the database creation correctly. Try it ;)
In the code below, the _connection is a
object by the way.
[Edit]
Modified the code so the exception is not swallowed anymore.