I have a C# application which uses the SSH.NET library to connect to a server. The application executes SQL commands to the database through multiple methods.
Is it better to have one long-running SSH connection that encompasses all SQL commands, eg:
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();
}
}
}
Or to open an SSH connection at the start of each SQL statement?
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();
}
}
}
The server is known to sometimes drop connections, so I imagine the second method is better in terms 'cleaner' logic for re-establishing a connection? Or are there any other better ways for reconnecting?
答案 0 :(得分:4)
使用 SQL连接的常见“最佳做法”是您要最小化连接打开时间-这意味着您在执行查询之前就打开了连接然后关闭它。 SSH连接也是如此。
您在使用后不处理的悬空资源都有一个名称,它们被称为内存泄漏。
如果SQL查询事务中的单个语句失败,则事务将失败。您要失败,请回滚错误ex:断开连接之前的状态数据库,然后稍后重试。
如果不需要记录错误,则可以使用set xact_abort on
,在发生错误(例如:超时或断开连接)的情况下事务自动回滚之前。
更多信息
通常,最佳实践是您不想避免失败,而是接受失败,快速失败,并有办法重试。您选择哪种策略重试由您决定。
如果您想做比手动重试更复杂的事情,那么我建议您看一下Rx observable(反应性扩展)或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));