无法立即连接到新创建的 SQL Server 数据库

Posted

技术标签:

【中文标题】无法立即连接到新创建的 SQL Server 数据库【英文标题】:Can't immediately connect to newly-created SQL Server database 【发布时间】:2012-03-07 00:20:08 【问题描述】:

我正在使用SQL Server Management Objects 创建一个数据库。

我写了如下方法来生成数据库:

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 并带有消息无法打开登录请求的数据库“数据库名称”。登录失败。 用户“用户”登录失败。

如果我尝试单步执行调试器中的语句,则会发生此异常从不,并且脚本可以正常执行。

我唯一的猜测是服务器需要一些时间来初始化数据库,然后才能打开它。这是准确的吗?除了尝试连接和连接失败之外,还有其他方法可以判断数据库是否准备就绪?

编辑:我应该提一下,在所有情况下都肯定会创建数据库。

编辑2: 在创建数据库之前,我调用EntityFramework.dll 的System.Data.Entity.Database.Exists 方法来检查数据库是否已经存在。如果我删除该呼叫,一切似乎都按预期工作。就好像该调用正在缓存结果并从查看新数据库中弄乱后续连接(无论他们是否使用实体框架)。

编辑 3: 我将 EntityFramework 的 Database.Exists 方法替换为使用 Server.Databases.Contains(databaseName) 的基于 SMO 的方法。我遇到了同样的问题,即创建后无法立即打开数据库。同样,如果我在创建之前不检查数据库是否存在,我可以在创建后立即打开它,但我希望能够在创建之前检查是否存在,所以我不会尝试创建现有数据库。

EntityFramework 的Database.Exists 和SMO 的Server.Databases.Contains 都只执行在master.sys.databases 中查找数据库名称的SQL。我不明白这为什么/如何干扰数据库连接。

【问题讨论】:

消息是否真的给你一个数据库名称“数据库名称”和一个用户“用户”?这可能是个问题。 该方法并没有真正告诉我们有关如何创建数据库的信息。您是否有可以发布的脚本或代码显示数据库的创建语句...? @shanabus:不,我只是将它们更改为不公开真实的数据库或登录名。 @DJKRAZE:我正在使用 SQL Server 管理对象的Database.Create。我没有编写自己的 CREATE DATABASE SQL 语句。 你不是在这个位置读到一些东西吗 createDatabaseObjectsScriptPath 在一个文件中..?? 【参考方案1】:

您必须在数据库创建方面有所不同。下面的代码正确处理数据库创建。试试看;)

私人无效创建数据库(字符串数据库名称) Microsoft.SqlServer.Management.Smo.Server sqlServer = 新的 Microsoft.SqlServer.Management.Smo.Server(_connection); 数据库 createdDatabase = new Database(); createdDatabase.Name = 数据库名称; createdDatabase.Parent = sqlServer; createdDatabase.Create();

在下面的代码中,_connection 是一个

Microsoft.SqlServer.Management.Smo.ServerConnection
对象。

[编辑] 修改了代码,使异常不再被吞没。

【讨论】:

这与我已经拥有的代码几乎相同,只是您正在吞下任何潜在的异常。我的创建逻辑已经有效。我在初始创建时没有遇到任何问题。 -1;与 OPs 代码基本相同,并默默吞下任何异常。 缺点是: 1. 前向兼容性 - SMO 版本 X 能否与 SQL Server 版本 (X+1) 或所有未来版本的 Azure SQL 一起工作?当然,TSQL CREATE DATABASE 会。 2. 学习曲线 - 众所周知的 SQL DDL 语句被不知名的 SMO 特定等价物替换。 3. 添加了一个新的依赖项(希望它现在是一个 Nuget 包)。这可能有自己的错误等。 4. 安全性。并不总是会出现问题,但可能会出现问题:很容易想象,与普通 TSQL 相比,某些 SMO 操作可能需要更多权限。【参考方案2】:

刚上线的数据库不一定准备好接受连接。要确定数据库何时可以接受连接,请查询 sys.databases 的 collat​​ion_name 列或 DATABASEPROPERTYEX 的 Collat​​ion 属性。当数据库排序规则返回非空值时,数据库可以接受连接。

【讨论】:

这个答案是正确的。记录在msdn.microsoft.com/en-us/library/ms186823.aspx。 不幸的是,此检查仅适用于禁用 auto_close 的数据库。 2008 / 2012 express 的许多默认配置将 auto_close 设置为启用,并且此检查会永远失败(尽管您可以连接,然后 Collat​​ion 属性变为非 NULL) 回应我自己:显然无法连接到新创建的数据库,但可以通过 ALTER DATABASE 设置选项。因此创建数据库,设置 AUTO_CLOSE OFF,检查排序规则值,然后再次设置 AUTO_CLOSE ON(如果这是您想要的 - 请考虑 sqlmag.com/blog/… 和 blogs.msdn.com/b/sqlsakthi/archive/2011/05/24/…)【参考方案3】:

登录请求的数据库名称。登录失败。用户“用户”登录失败

这里要注意的一点是错误消息是围绕安全性的。您如何尝试登录到新数据库(即,连接字符串用于新数据库连接的安全类型)?如果您使用 SQL 身份验证,则需要发出 sp_adduser 以授予对数据库的登录访问权限。

http://msdn.microsoft.com/en-us/library/ms181422.aspx

【讨论】:

【参考方案4】:

在我的例子中,问题不在于新创建的数据库还没有准备好。但问题是SqlConnection.Open() 显然使用了失败的缓存连接,然后又返回了同样的错误。

当我在尝试打开新创建的数据库之前调用静态SqlConnection.ClearAllPools() 方法时,它工作正常!

另请参阅this 问题。

【讨论】:

以上是关于无法立即连接到新创建的 SQL Server 数据库的主要内容,如果未能解决你的问题,请参考以下文章

无法连接到新的Azure SQL Server实例

sqlserver数据库表数据误删除了 怎么恢复

由于登录失败错误,无法连接到 SQL Server 数据库 [重复]

SetPropertyValue 期间的 CreateUserWizard 错误:无法连接到 SQL Server 数据库

如何解决SQL Server 2008 无法连接到

ASP.NET MVC 4 EF6 无法连接到 SQL Server Express 数据库