我正在使用C#和SQL LocalDB 2012作为数据库引擎构建Windows窗体应用程序。该应用程序第一次启动时,我想创建一个数据库服务器的新实例,创建一个新的登录名并禁用默认的Windows登录名,以防止用户访问行数据库。 首先,我尝试使用Connection.Open()来查看实例和新登录是否正常。如果遇到异常,我将调用两个过程来创建新实例并登录。
我正在经历一个奇怪的情况。创建新实例,创建新登录名并禁用默认的Windows登录名后,SqlConnection.Open()会引发异常。奇怪的是,如果我执行以下两项操作之一,则连接将正常打开而不会出现异常:
1-如果我逐步在调试模式下运行代码,它将正常工作。如果我按“开始”按钮正常运行相同的代码,则会引发异常。
2-如果我注释掉初始代码,然后尝试在Connection.Open()中查看实例和登录名是否已创建-如果我注释掉了Conneciton.Open()并强制代码创建一个新实例和登录名,不会引发异常。
这是我的代码。我删除了不相关的部分。
// The below throws an exception
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows;
class Program
{
const string connectionString = @"Data Source=(localdb)\MyInstance;User Id=NewLogin;Password=test123;";
const string TestConnectionString = @"Data Source=(localdb)\MyInstance;Integrated Security=true;";
const string DBInstanceName = "MyInstance";
// To replicate, replace 'Ahmad-PC\Ahmad' with your Windows login
const string changeDBUserSQL =
@" IF EXISTS(SELECT * FROM sys.server_principals WHERE name = N'NewLogin')" +
@" DROP LOGIN[NewLogin]" +
@" CREATE LOGIN NewLogin" +
@" WITH PASSWORD = 'test123';" +
@" CREATE USER NewUser FOR LOGIN NewLogin; " +
@" EXEC master..sp_addsrvrolemember @loginame = N'NewLogin', @rolename = N'sysadmin' " +
@" IF EXISTS(SELECT * FROM sys.server_principals WHERE name = N'Ahmad-PC\Ahmad')" +
@" EXEC master..sp_dropsrvrolemember @loginame = N'Ahmad-PC\Ahmad', @rolename = N'sysadmin' ";
static void Main(string[] args)
{
startup();
}
static void startup()
{
SqlConnection testCon = new SqlConnection();
bool NamedInstanceExists = false;
try
{
testCon.ConnectionString = connectionString;
testCon.Open();
}
catch (Exception ex)
{
NamedInstanceExists = false;
}
finally
{
if (testCon.State == ConnectionState.Open) testCon.Close();
testCon.Dispose();
}
if (!NamedInstanceExists)
{
CreateNamedDBInstance();
CreateNewDBUser();
}
SqlConnection conn2;
conn2 = new SqlConnection();
conn2.ConnectionString = connectionString;
try
{
// An exception is thrown here
conn2.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public static void CreateNamedDBInstance()
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "sqllocaldb.exe";
startInfo.Arguments = "create " + DBInstanceName;
process.StartInfo = startInfo;
try
{
process.Start();
}
catch (Exception ex)
{
}
while (!process.HasExited) ;
}
public static void CreateNewDBUser()
{
SqlConnection myConn = new SqlConnection(TestConnectionString);
SqlCommand myCommand = new SqlCommand(changeDBUserSQL, myConn);
try
{
myConn.Open();
myCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (myConn.State == ConnectionState.Open) myConn.Close();
myCommand.Dispose();
myConn.Dispose();
}
}
}
抛出的异常是
建立与SQL Server的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称正确,并且已将SQL Server配置为允许远程连接。 (提供者:SQL网络接口,错误:50-发生本地数据库运行时错误。指定的LocalDB实例不存在。
编辑1,编辑了上面的代码,现在可以复制 如果对代码进行以下更改,则它将毫无例外地运行到最后: 第32行,加入
bool NamedInstanceExists = false;
注释第36行:
// testCon.Open();