如何避免异步数据库连接时出现 "访问违规"?

问题描述 投票:1回答:2

目标:正确使用ExecuteAsync。

我知道我的应用程序本身至少是 差不离 纠正,因为它执行正确 曾经所以我知道我可以排除防火墙、错误的数据库密码、过程名等常见的嫌疑。

private async Task<T> executeAsyncHelper<T>(Func<IDataReader, T> then)
{
    using (SqlConnection conn = new SqlConnection(connectionString))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(name, conn))
        {
            parameters.Select(p => cmd.Parameters.Add(p))
                .ToImmutableList(); 
            cmd.CommandType = CommandType.StoredProcedure;
            using (IDataReader rdr = await cmd.ExecuteReaderAsync())
            {
                return then(rdr);
            }
        }
    }
}

问题。违反访问规定 第二次 SqlConnection.Open()

该方法在同一个过程中被调用两次。第一次,它成功地更新了数据库。第二次,整个过程在 conn.Open() 与 "访问违规"。重要的是,它没有抛出异常。而是整个调试器以负状态码退出。

这是调试器输出的最后两行(其余的调试器输出看起来很正常)。

The program '[6904] dotnet.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.  
The program '[6904] dotnet.exe: Program Trace' has exited with code 0 (0x0).

这种行为是100%可重复的

假设。连接池和非同步性

据我看,最可能的原因是异步打开两个连接时出现了一些问题,但我并不马上知道该怎么做 与这个假设。我已经把方法写得很安全,因为我知道如何写。

其次,我检查了我的Azure SQL Server实例是否对它有任何异常限制。这是一个基本的实例,但我怀疑这是问题所在,因为如果是这个问题的话,我预计会出现SQL异常(调试器会在这个异常上中断并显示正常的堆栈跟踪)。

环境信息

  • Azure SQL Server 2016
  • Windows 10
  • .NET核心2.1
  • Visual Studio 2017

结论

有没有人看到我的实现方式有什么问题,或者有什么建议来了解更多的错误?

c# .net-core ado.net task-parallel-library sqlconnection
2个回答
0
投票

试试这个。

private async Task<T> executeAsyncHelper<T>(Func<IDataReader, Task<T>> then)
{
    using (SqlConnection conn = new SqlConnection(connectionString))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(name, conn))
        {
            parameters.Select(p => cmd.Parameters.Add(p))
                .ToImmutableList(); 
            cmd.CommandType = CommandType.StoredProcedure;
            using (IDataReader rdr = await cmd.ExecuteReaderAsync())
            {
                return await then(rdr);
            }
        }
    }
}

请注意签名的变化,并在等待 return.


0
投票

你可以检查一下你是否遇到了连接限制,你可以执行exec sp_who2,看看你的sql服务器上有多少连接。如果sql服务器上显示有很多连接,那可能是资源问题造成的。你有没有尝试过在常规的同步运行这段代码,是否会导致同样的问题?在你的连接字符串中是否有任何限制连接数的东西?由于我没有看到这段代码的上下文,所以只是抛出一些理论。


0
投票

很自信我想明白了。其实这和程序死机的准确线路没有任何关系。

而是程序在另一个线程的其他地方溢出了栈。这个 conn.Open() 是一个红色的鲱鱼,尽管那是调试器在失败前总是指向的地方。我的猜测是 conn.Open() 只是资源密集型的,足以让它超过边缘,让它看起来像那是导致它的原因。

为了将来的参考,如果你得到 "访问违规",重构为同步代码,然后调试器就可以直接走过去,实际上抛出StackOverflowException,而不是直接崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.