9

我注意到sqlWrite.ExecuteNonQuery();在几秒钟内执行 200 次插入查询后我的代码错误。我一直认为这using将确保资源被正确地重用,并且不需要做任何事情。这是我第一次遇到这个错误,我已经处理 sql/c# 近 3 年了,做不同的事情。

using (SqlConnection varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
{
    using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) 
    {
        sqlWrite.Parameters.AddWithValue("@var_agr_fname", var_agr_fname == "" ? (object) DBNull.Value : var_agr_fname);
        sqlWrite.ExecuteNonQuery();
    }
}


public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails)
{
    var sqlConnection = new SqlConnection(varSqlConnectionDetails);
    try
    {
        sqlConnection.Open();
    }
    catch
    {
        DialogResult result = MessageBox.Show(new Form {TopMost = true},
                                              "Błąd połączenia z bazą danych. Czy chcesz spróbować nawiązac połączenie ponownie?",
                                              "Błąd połączenia (000001)",
                                              MessageBoxButtons.YesNo,
                                              MessageBoxIcon.Stop);
        if (result == DialogResult.No)
        {
            if (Application.MessageLoop)
            {
                Application.Exit(); // Use this since we are a WinForms app
            }
            else
            {
                Environment.Exit(1); // Use this since we are a console app
            }
        }
        else
        {
            sqlConnection = sqlConnectOneTime(varSqlConnectionDetails);
        }
    }
    return sqlConnection;
}

错误信息:A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)

考虑到此错误的建议,我应该使用SqlConnection.ClearAllPools();它来确保正确重置或丢弃连接。所以我可以使用它,但问题是在哪里以及何时使用它?如何知道限制是否会被打破?极限在哪里?在 50 / 150 / 200 ?还是我应该在循环中每次都使用它?

4

3 回答 3

5

首先,让我说这段代码太可怕了。您将 UI 与数据连接创建混合在一起。更重要的是,您在一个部分内显示一个对话窗口catch并进行递归调用!这是非常混乱的,它本身就可能导致错误和不可预测的行为。并且(原始)格式使其难以阅读。很抱歉评论很苛刻,但你真的应该重新设计这段代码。

除此之外,您的代码应该可以正常工作,但如果您遇到No process is on the other end of the pipe.错误,则意味着您的数据库和/或 SQL Server 有问题。看起来它被堵塞了,只是不再接受任何连接。如果您在短时间内运行一批插入,请尽可能在一个连接上进行。ClearAllPools是一种在发生错误时恢复的方法,最好找出它是什么而不是掩盖它。这就像当您的牙齿疼痛并且从不去看牙医时服用扑热息痛一样。

另一件事是使用多个 SqlConnections 为每个连接创建单独的事务。这增加了 SQL Server 的负载,尽管它确实可以每秒执行超过数百个事务。

此外,您可以将传输更改为命名管道和 TCP,以查看它是否更改了任何内容。

于 2012-04-04T22:37:49.907 回答
4

“我有一种方法,我可以通过使用它一次或多次来重用它。它完成了从建立连接(或使用已经连接的连接)到将连接返回到池的所有过程。这些是我得到的建议。这样如果连接打开,我总是会重复使用它,如果它关闭,我总是打开它。”

这听起来像是您重新发明了连接池。如果它们关闭,它总是重用连接,如果它们打开,它不能重用它们。

所以关闭catch块中的连接:

public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails) {
    var sqlConnection = new SqlConnection(varSqlConnectionDetails);
    try {
        sqlConnection.Open();
    } catch {
        //log and
        sqlConnection.Close();
        throw
    }
    return sqlConnection;
}

编辑:说实话,我根本不会使用这样的工厂方法。它们只是不可重现错误的来源。在您使用它的地方创建和打开连接如此耗时?

using(SqlConnection varConnection = new SqlConnection(Locale.sqlDataConnectionDetails)) {
    using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) {
        sqlWrite.Parameters.AddWithValue("@varSecus_agr_fname", varSecus_agr_fname == "" ? (object) DBNull.Value : varSecus_agr_fname);
        varConnection.Open();
        sqlWrite.ExecuteNonQuery();
    }
}

前两个链接来自您的链接问题(不是接受的答案),它们也可能会有所帮助:

于 2012-04-04T22:04:24.027 回答
0

这两个错误:

向服务器发送请求时发生传输级错误。(提供者:TCP 提供者,错误:0 - 现有连接被远程主机强行关闭。)

向服务器发送请求时发生传输级错误。(提供者:共享内存提供者,错误:0 - 管道的另一端没有进程。)

与在 1900 年之前将 DateTime 值插入 SQL 相关。此处的 Microsoft 规则是 .. 不要在 SQL 中的 DateTime 值中存储小于 1900 年的 DateTime 值。改用字符串...

于 2012-04-05T08:30:26.283 回答