![](/img/trans.png)
[英]Does using (var connection = new SqlConnection(“ConnectionString”)) still close/dispose the connection on error?
[英]Using or Dispose of SqlConnection not working, but Close does?
我已经阅读了很多关于为什么你应该优先using
语句而不是手动执行.Open()
然后.Close()
和最后.Dispose()
的文章。
当我最初编写代码时,我有这样的事情:
private static void doIt(string strConnectionString, string strUsername)
{
SqlConnection conn = new SqlConnection(strConnectionString);
try
{
conn.Open();
string strSqlCommandText = $"CREATE USER {strUsername} for LOGIN {strUsername} WITH DEFAULT SCHEMA = [dbo];";
SqlCommand sqlCommand = new SqlCommand(strSqlCommandText, conn);
var sqlNonReader = sqlCommand.ExecuteNonQuery();
if (sqlNonReader == -1) Utility.Notify($"User Added: {strUsername}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
conn.Close();
conn.Dispose();
}
}
这行得通……没问题。 但只有一次。
所以,如果我做这样的事情:
private static void doItLots(string strConnectionString, string strUsername)
{
for(int i=0; i<10; i++)
{
doIt(strConnectionString, $"{strUsername}_{i}");
}
}
它在i=0
时第一次工作,但任何后续迭代都失败, Cannot open database "myDbName" requested by the login. The login failed.
Cannot open database "myDbName" requested by the login. The login failed.
但是,如果我返回 go 并注释掉conn.Dispose();
行,那么它在所有迭代中都可以正常工作。
问题很简单,如果我想在方法之外执行.Dispose()
部分,那么我不得不传递SqlConnection
object 而不是简单地传递凭据,这可能会使我的代码不那么可移植,然后我需要保持连接的时间更长。 我一直认为您想快速打开和关闭连接,但显然我误解了.Dispose()
命令的工作方式。
正如我在一开始所说的那样,我也尝试过这样using
......
private static void doIt(string strConnectionString, string strUsername)
{
using (SqlConnection conn = new SqlConnection(strConnectionString))
{
try
{
conn.Open();
string strSqlCommandText = $"CREATE USER {strUsername} for LOGIN {strUsername} WITH DEFAULT SCHEMA = [dbo];";
SqlCommand sqlCommand = new SqlCommand(strSqlCommandText, conn);
var sqlNonReader = sqlCommand.ExecuteNonQuery();
if (sqlNonReader == -1) Utility.Notify($"User Added: {strUsername}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
conn.Close();
}
}
}
这与手动调用.Dispose()
的初始代码完全相同。
在这里的任何帮助将不胜感激。 我很想转换为using
语句,但无法弄清楚如何以这种方式编写可重用的方法......
更新:
我已经缩小了一点。 问题不在于迭代或一遍又一遍地调用。 但我仍然遇到访问错误。 这是代码:
string strConnectionString = $@"Data Source={StrSqlServerDataSource};Initial Catalog={StrDatabaseName};User id={StrSqlServerMasterUser};Password={StrSqlServerMasterPassword}";
using (SqlConnection connUserDb = new SqlConnection(strConnectionString))
{
try
{
Utility.Notify($"Connection State: {connUserDb.State.ToString()}"); // Responds as 'Closed'
connUserDb.Open(); // <-- throws error
Utility.Notify($"Connection State: {connUserDb.State.ToString()}");
Utility.Notify($"MSSQL Connection Open... Adding User '{strUsername}' to Database: '{strDatabaseName}'");
string sqlCommandText =
//$@"USE {StrDatabaseName}; " +
$@"CREATE USER [{strUsername}] FOR LOGIN [{strUsername}] WITH DEFAULT_SCHEMA = [dbo]; " +
$@"ALTER ROLE [db_datareader] ADD MEMBER [{strUsername}]; " +
$@"ALTER ROLE [db_datawriter] ADD MEMBER [{strUsername}]; " +
$@"ALTER ROLE [db_ddladmin] ADD MEMBER [{strUsername}]; ";
using (SqlCommand sqlCommand = new SqlCommand(sqlCommandText, connUserDb))
{
var sqlNonReader = sqlCommand.ExecuteNonQuery();
if (sqlNonReader == -1) Utility.Notify($"User Added: {strUsername} ({sqlNonReader})");
}
result = true;
}
catch (Exception ex)
{
Utility.Notify($"Creating User and Updating Roles Failed: {ex.Message}", Priority.High);
}
finally
{
connUserDb.Close();
Utility.Notify($"MSSQL Connection Closed");
}
}
return result;
}
我在这里遇到的错误是: Cannot open database requested by the login. The login failed.
Cannot open database requested by the login. The login failed.
我得到的一个线索是,在此之前,我运行的是相同的代码,但有两个更改:
1) 取消注释sqlCommandText
中的USE
语句 2) 改为连接到Master
数据库
当我这样做时,它也不起作用,而是出现此错误: The server principal is not able to access the database under the current security context.
如果我将 go 放入 SSMS 并查看它们被列为db_owner
的 MasterUser,我可以执行我想要的任何活动,包括运行上面代码中包含的命令。
根据此处的建议,我重写了所有代码以使用单个连接。 在遇到“服务器主体”错误后,我又添加了一个连接以尝试直接连接到该数据库而不是master
。
更新 2:
这是另一个 plot 扭...
这可以在我的本地计算机上正常工作(现在)。 但是,从针对运行 MSSQL 的 Amazon Web 服务 (AWS) 关系数据库服务器 (RDS) 的 Azure Web 作业运行时,不能(总是)工作。
我明天必须审核 git 提交,但截至今天下午 5 点,它在本地和 Azure 上都有效。 上次更新后,我能够测试本地并让它工作,但是当在 Azure Webjob 上运行时,它如上所述失败。
SqlConnection 实现 IDisposable。 您不调用 dispose 或 close。
try{
using (SqlConnection conn = new SqlConnection(strConnectionString))
{
conn.Open();
string strSqlCommandText = $"CREATE USER {strUsername} for LOGIN {strUsername} WITH DEFAULT SCHEMA = [dbo];";
SqlCommand sqlCommand = new SqlCommand(strSqlCommandText, conn);
var sqlNonReader = sqlCommand.ExecuteNonQuery();
if (sqlNonReader == -1) Utility.Notify($"User Added: {strUsername}");
}}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.