-2

我有一个以异步方式使用 TCP 套接字的 C# 项目。

每个请求都来自客户端并从 SQL Server 存储过程中提出问题,在问题结束后打开和关闭 SQL 连接。

我用过这段代码:

using (var con = new SqlConnection(setting.ConnectionString))
{
    try
    {
        //some codes (edited)
        SqlCommand command = new SqlCommand(con);
        command.CommandText = "procedurename1";
        command.CommandType = CommandType.StoredProcedure; 
        command.Parameters.Add(new SqlParameter("@name", sb.ToString()));
        SqlDataAdapter adapter = new SqlDataAdapter(command);
        try
                {
                    adapter.Fill(dataSet);
                }
                catch (Exception ex)
                {
                    con.Close();
                    con.Dispose();
                    throw ex;
                }
                finally {
                    con.Close();
                    con.Dispose();
                }
    }
    catch(Exception ex)
    {}
    finally
    {
        con.close();
        con.dispose();
    }
}

我用过

netstat -a -n | find /c "1433"

计算打开和关闭的 SQL 连接。

问题是 SQL 连接数增加,它很少减少和倒计时。

主要问题,当我的程序在大约 30 分钟的大量请求下工作时,我得到

SqlCommand 超时错误(默认 30 秒过去)

重新启动我的 C# 程序后,SqlCommand超时将消失。

这是我的程序或 SQL Server 端的问题吗?

请记住,它总是调用 SQL Server 中的存储过程,而不是直接执行查询。

主要方法:

public void main()
{
Task.Factory.StartNew(() =>
                    {                        
                        allDone.Reset();
                        mySocket.AcceptAsync(e);
                        allDone.WaitOne();                       
                    });
}

public void e_Completed(object sender, SocketAsyncEventArgs e)
        {
            var socket = (Socket)sender;
            ThreadPool.QueueUserWorkItem(HandleTcpRequest, e.AcceptSocket);
            e.AcceptSocket = null;
            socket.AcceptAsync(e);
        }

public void HandleTcpRequest(object state)
{
    //do some code and connection to SQL server
    DLL.Request httprequest = new DLL.Request(dataSet.Tables[0], fileDt);
    DLL.IHttpContext _context = new DLL.HttpContext(httprequest);
    _context.GetResults();
}
4

2 回答 2

1

由于我们看不到“//一些代码”,我将根据我们可以看到的有限的 Sql 相关代码的编写方式进行远景。

我猜想SqlCommand、DataReader、SqlDataAdapter、TransactionScope 等一些一次性的东西不在“使用”块中,所以在数据库上保持资源打开。

还值得提出这种问题的可能性,即问题中显示的代码或访问该数据库的任何其他程序,包括您自己的应用程序和 SSMS(例如,如果开发人员在窗口中运行未提交的事务) .

PS 我建议删除 using 块中的所有内容,除了“//一些代码”部分。

添加更多代码后更新

这是您更正后的代码。这将确保资源得到处理,这将防止可能导致您的问题的资源泄漏。

    using (var con = new SqlConnection(setting.ConnectionString))
    {
        //some codes (edited)
        using (SqlCommand command = new SqlCommand(con))
        {
            command.CommandText = "procedurename1";
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add(new SqlParameter("@name", sb.ToString()));
            using (var adapter = new SqlDataAdapter(command))
            {
                adapter.Fill(dataSet);
            }
        }
    }

PS永远不要写“throw ex;” 再次从内部捕获。它会导致堆栈跟踪丢失 - 只需使用“throw;”。

于 2018-03-11T21:42:24.523 回答
1

主要问题是当我的程序在大约 30 分钟的大量请求下工作时,

为了隔离超时的根本问题,我建议测试独立于 TCP 套接字调用的存储过程的 sql 查询 30 分钟,并记录超时异常详细信息以供检查

在 30 分钟内运行以下查询以模拟您的工作环境:

     public void RunQuery()
     {
        using (var con = new SqlConnection(setting.ConnectionString))
        {
            try
            {
                //some codes
            }
            catch(SqlException ex)
            {
            //test for timeout
                if (ex.Number == -2) {
                Console.WriteLine ("Timeout occurred");
                // log ex details for more inspection
                }
            }

        }

    }

阅读如何正确处理 CommandTimeout?

当您使用异步调用时,我建议您尝试使用基于任务的异步编程模型 (TAP)的异步数据库调用

于 2018-03-11T21:52:13.637 回答