简体   繁体   English

使用或处置 SqlConnection 不起作用,但 Close 可以吗?

[英]Using or Dispose of SqlConnection not working, but Close does?

I have read the numerous posts on why you should give the using statement preference over manually doing .Open() then .Close() and finally .Dispose() .我已经阅读了很多关于为什么你应该优先using语句而不是手动执行.Open()然后.Close()和最后.Dispose()的文章。

When I initially wrote my code, I had something like this:当我最初编写代码时,我有这样的事情:

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();
    }
}

and this works... no problem.这行得通……没问题。 but only ONCE.但只有一次。

so, if I do something like this:所以,如果我做这样的事情:

private static void doItLots(string strConnectionString, string strUsername)
{
    for(int i=0; i<10; i++)
    {
        doIt(strConnectionString, $"{strUsername}_{i}");
    }
}

it works the FIRST time when i=0 , but any subsequent iterations fail with Cannot open database "myDbName" requested by the login. The login failed.它在i=0时第一次工作,但任何后续迭代都失败, Cannot open database "myDbName" requested by the login. The login failed. Cannot open database "myDbName" requested by the login. The login failed.

However, if I go back and comment out the conn.Dispose();但是,如果我返回 go 并注释掉conn.Dispose(); line, then it works fine on all iterations.行,那么它在所有迭代中都可以正常工作。

The problem is simply that if I want to do the .Dispose() part outside of the method, then I am forced to pass a SqlConnection object instead of simply passing the credentials, potentially making my code a bit less portable and then I need to keep the connection around longer as well.问题很简单,如果我想在方法之外执行.Dispose()部分,那么我不得不传递SqlConnection object 而不是简单地传递凭据,这可能会使我的代码不那么可移植,然后我需要保持连接的时间更长。 I was always under the impression that you want to open and close connections quickly but clearly I'm misunderstanding the way the .Dispose() command works.我一直认为您想快速打开和关闭连接,但显然我误解了.Dispose()命令的工作方式。

As I stated at the outset, I also tried doing this with using like this...正如我在一开始所说的那样,我也尝试过这样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();
        }
    }
}

and this does the exact same thing as the initial code with .Dispose() called manually.这与手动调用.Dispose()的初始代码完全相同。

Any help here would be greatly appreciated.在这里的任何帮助将不胜感激。 I'd love to convert to the using statements but having trouble figuring out how to write reusable methods that way...我很想转换为using语句,但无法弄清楚如何以这种方式编写可重用的方法......

UPDATE:更新:

I have narrowed it down a bit.我已经缩小了一点。 The issue is NOT the iterations or making the calls over-and-over again.问题不在于迭代或一遍又一遍地调用。 But I am still getting an access error.但我仍然遇到访问错误。 Here is the code:这是代码:

        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;
    }

The error I am getting here is: Cannot open database requested by the login. The login failed.我在这里遇到的错误是: Cannot open database requested by the login. The login failed. Cannot open database requested by the login. The login failed.

One clue I have is that prior to this, I was running this same code with two changes:我得到的一个线索是,在此之前,我运行的是相同的代码,但有两个更改:

1) uncommented the USE statement in the sqlCommandText 2) connected to the Master database instead 1) 取消注释sqlCommandText中的USE语句 2) 改为连接到Master数据库

When I did that, it didn't work either, and instead I got this error: The server principal is not able to access the database under the current security context.当我这样做时,它也不起作用,而是出现此错误: The server principal is not able to access the database under the current security context.

If I go into SSMS and review the MasterUser they are listed as db_owner and I can perform any activities I want, including running the command included in the code above.如果我将 go 放入 SSMS 并查看它们被列为db_owner的 MasterUser,我可以执行我想要的任何活动,包括运行上面代码中包含的命令。

I rewrote all the code to make use of a single connection per the recommendations here.根据此处的建议,我重写了所有代码以使用单个连接。 After running into the "server principal" error, I added one more connection to attempt to directly connect to this database rather than the master .在遇到“服务器主体”错误后,我又添加了一个连接以尝试直接连接到该数据库而不是master

UPDATE 2:更新 2:

Here is another plot twist...这是另一个 plot 扭...

This is working from my local computer fine (now).这可以在我的本地计算机上正常工作(现在)。 But, not (always) working when run from an Azure Webjob that targets an Amazon Web Services (AWS) Relational Database Server (RDS) running MSSQL.但是,从针对运行 MSSQL 的 Amazon Web 服务 (AWS) 关系数据库服务器 (RDS) 的 Azure Web 作业运行时,不能(总是)工作。

I will have to audit the git commits tomorrow, but as of 5p today, it was working on BOTH local and Azure.我明天必须审核 git 提交,但截至今天下午 5 点,它在本地和 Azure 上都有效。 After the last update, I was able to test local and get it to work, but when run on Azure Webjob it failed as outlined above.上次更新后,我能够测试本地并让它工作,但是当在 Azure Webjob 上运行时,它如上所述失败。

SqlConnection implements IDisposable. SqlConnection 实现 IDisposable。 You don't call dispose or close.您不调用 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.

相关问题 使用(var connection = new SqlConnection(“ ConnectionString”))是否仍会关闭/将连接置于错误状态? - Does using (var connection = new SqlConnection(“ConnectionString”)) still close/dispose the connection on error? 我是否需要明确地关闭和处置 SQLConnection? - Do I need to close and dispose the SQLConnection explicitly? 如果没有调用SqlConnection.Close()或SqlConnection.Dispose(),它会是什么? - What will it be if SqlConnection.Close() or SqlConnection.Dispose() is not called? SqlConnection/SqlCommand 在 Close 和 Dispose 后保持数据库处于使用状态 - SqlConnection/SqlCommand keeps database in use after Close and Dispose 使用SqlTransaction时关闭SqlConnection - Close SqlConnection while using SqlTransaction 关闭 SqlConnection 不会关闭 SQL 上的关闭事务 - Closing a SqlConnection does not close the close the transaction on SQL 如果我在方法中使用 SqlCommand 作为参数,它会阻止 SqlConnection 处置吗? - If I use SqlCommand in a method as a parameter, does it block a SqlConnection dispose? SqlDataAdapter是否在Fill()函数之后关闭SqlConnection? - Does SqlDataAdapter close the SqlConnection after Fill() function? 这是处理SQLConnection的正确方法吗? - Is this the right way to dispose the SQLConnection 使用“使用”时最后关闭SqlConnection - Close SqlConnection in the Finally when using “Using”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM