我正在使用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:我使用Database.Exists
将基于SMO的方法替换为EntityFramework的Server.Databases.Contains(databaseName)
方法。我得到同样的问题,因为创建后无法立即打开数据库。同样,如果我在创建之前没有检查数据库是否存在,我可以在创建之后立即打开它,但我希望能够在创建之前检查存在,所以我不会尝试创建现有数据库。
EntityFramework的Database.Exists
和SMO的Server.Databases.Contains
都只执行在master.sys.databases中查找数据库名称的SQL。我不明白为什么/如何干扰数据库连接。
答案 0 :(得分:7)
刚上线的数据库不一定准备好接受连接。要确定数据库何时可以接受连接,请查询sys.databases的collation_name列或DATABASEPROPERTYEX的Collation属性。当数据库排序规则返回非空值时,数据库可以接受连接。
答案 1 :(得分:1)
这里要注意的一件事是错误信息是围绕安全性的。您是如何尝试登录新数据库的(即用于新数据库连接的连接字符串是什么类型的安全性)?如果您使用的是SQL身份验证,则需要发出sp_adduser以授予对数据库的登录访问权限。
答案 2 :(得分:1)
在我的情况下,事实证明问题不是新创建的数据库没有准备好。但问题是echo "hello";
显然使用了失败的缓存连接,然后再次返回相同的错误。
在我尝试打开新创建的数据库之前调用静态SqlConnection.ClearAllPools()
方法时,它运行正常!
另见this问题。
答案 3 :(得分:0)
您必须在数据库创建方面略有不同。下面的代码正确处理数据库创建。试试吧;)
private void CreateDatabase(string databaseName) { Microsoft.SqlServer.Management.Smo.Server sqlServer = new Microsoft.SqlServer.Management.Smo.Server(_connection); Database createdDatabase = new Database(); createdDatabase.Name = databaseName; createdDatabase.Parent = sqlServer; createdDatabase.Create(); }
在下面的代码中,顺便说一句,_connection是一个
Microsoft.SqlServer.Management.Smo.ServerConnection对象。
[编辑] 修改了代码,因此不再吞下异常。