C# C SSH.NET-一个SSH连接与多个SSH连接

C# C SSH.NET-一个SSH连接与多个SSH连接,c#,mysql,database,ssh,ssh.net,C#,Mysql,Database,Ssh,Ssh.net,我有一个C应用程序,它使用库连接到服务器。应用程序通过多种方法对数据库执行SQL命令 最好有一个包含所有SQL命令的长时间运行的SSH连接,例如: using (var sshClient = getSshClient())) { sshClient.Connect(); if (sshClient.IsConnected) { using (var portForward = setupPortForward())) {

我有一个C应用程序,它使用库连接到服务器。应用程序通过多种方法对数据库执行SQL命令

最好有一个包含所有SQL命令的长时间运行的SSH连接,例如:

using (var sshClient = getSshClient()))
{
    sshClient.Connect();

    if (sshClient.IsConnected)
    {
        using (var portForward = setupPortForward()))
        {
            sshClient.AddForwardedPort(setupPortForward());
            portForward.Start();

            // Start SQL commands

            if (!sshClient.IsConnected) {
                sshClient.Connect();
            }
            else {
                executeSQLCommand1();
            }

            if (!sshClient.IsConnected) {
                sshClient.Connect();
            }
            else {
                executeSQLCommand2();
            }

            // End SQL commands

            portForward.Stop();
            sshClient.Disconnect();
        }
    }
}
或者在每个SQL语句的开头打开SSH连接

using (var sshClient = setupSshClient()))
{
    sshClient.Connect();

    if (sshClient.IsConnected)
    {
        using (var portForward = setupPortForward()))
        {
            sshClient.AddForwardedPort(portForward);
            portForward.Start();

            executeSQLCommand1();

            portForward.Stop();
            sshClient.Disconnect();
        }
    }
}

using (var sshClient = setupSshClient()))
{
    sshClient.Connect();

    if (sshClient.IsConnected)
    {
        using (var portForward = setupPortForward()))
        {
            sshClient.AddForwardedPort(portForward);
            portForward.Start();

            executeSQLCommand2();

            portForward.Stop();
            sshClient.Disconnect();
        }
    }
}
众所周知,服务器有时会断开连接,所以我认为第二种方法在“更干净”的逻辑方面更适合于重新建立连接?或者有其他更好的重新连接方法吗?

第1部分:最小化连接寿命。 SQL连接的一个常见最佳实践是,您希望最小化连接打开时间—这意味着您在执行查询之前打开连接,然后在执行查询之后关闭连接。SSH连接也是如此

在使用后不处理的悬空资源有一个名称,它们被称为内存泄漏

第2部分:使用事务确保数据库状态一致性 如果SQL查询事务中的一条语句失败,则该事务将失败。如果要失败,请回滚数据库在错误ex:连接已断开之前的状态,然后重试

如果不需要记录错误,则可以在事务发生错误(例如:超时或断开连接)时,在事务自动回滚之前使用set xact_abort on

更多信息

第3部分:创建重试策略 一般来说,最好的做法是你不想避免失败,而是接受失败,快速失败,并有办法再试一次。您为重试选择何种策略取决于您

如果您想做任何比手动重试更复杂的事情,那么我建议您查看Rx可观察反应性扩展或Polly。它确实有一点学习曲线,但你会习惯的

 // Policy to retry 5 times, waiting {2, 4, 8, 16, 32} seconds between retries.
 var policy = Policy
   .Handle<SqlException>()
   .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

 policy.Execute(() => UpdateDatabase1(obj1));
第1部分:最小化连接寿命。 SQL连接的一个常见最佳实践是,您希望最小化连接打开时间—这意味着您在执行查询之前打开连接,然后在执行查询之后关闭连接。SSH连接也是如此

在使用后不处理的悬空资源有一个名称,它们被称为内存泄漏

第2部分:使用事务确保数据库状态一致性 如果SQL查询事务中的一条语句失败,则该事务将失败。如果要失败,请回滚数据库在错误ex:连接已断开之前的状态,然后重试

如果不需要记录错误,则可以在事务发生错误(例如:超时或断开连接)时,在事务自动回滚之前使用set xact_abort on

更多信息

第3部分:创建重试策略 一般来说,最好的做法是你不想避免失败,而是接受失败,快速失败,并有办法再试一次。您为重试选择何种策略取决于您

如果您想做任何比手动重试更复杂的事情,那么我建议您查看Rx可观察反应性扩展或Polly。它确实有一点学习曲线,但你会习惯的

 // Policy to retry 5 times, waiting {2, 4, 8, 16, 32} seconds between retries.
 var policy = Policy
   .Handle<SqlException>()
   .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

 policy.Execute(() => UpdateDatabase1(obj1));

如果服务器倾向于断开连接,它甚至可以在命令执行过程中断开一个连接。因此,在任何情况下,您都必须处理重新连接。设置+设置+转发+启动+停止+断开连接需要多长时间?您的第二个选择是将MySQL每秒的查询限制在这一范围内。您使用SSH连接和sql命令,而不是使用relavent数据库客户端库,这有什么原因吗?这种方法无论是长时间运行还是单个命令都可能在连接断开时引起问题,如果使用数据库客户机,则更容易处理错误处理。一些难以处理的问题是,如果连接断开,最后一个SQL命令是否成功完成?即使连接保持活动状态,解析输出流中的错误也会很麻烦。您的事务需求是什么?每个sql命令是否都是原子的,或者它们是否需要包装在事务中,如果是,则需要第一种长时间运行的连接方法。如果服务器倾向于删除连接,则它甚至可以在某个命令中间删除一个连接。因此,在任何情况下,您都必须处理重新连接。设置+设置+转发+启动+停止+断开连接需要多长时间?您的第二个选择是将MySQL每秒的查询限制在这一范围内。您使用SSH连接和sql命令,而不是使用relavent数据库客户端库,这有什么原因吗?这种方法无论是长时间运行还是单个命令都可能在连接断开时引起问题,如果使用数据库客户机,则更容易处理错误处理。一些难以处理的问题是
如果连接断开,最后一个SQL命令是否成功完成?即使连接保持活动状态,解析输出流中的错误也会很麻烦。您的事务需求是什么?每个sql命令都是原子的还是需要包装在事务中,如果是这样,那么您需要第一个长时间运行的连接方法。