【发布时间】:2018-06-02 12:48:06
【问题描述】:
朋友们,我有一个关于在执行 SQL 命令时实施简单重试策略的问题。
我的问题是:重试循环应该封装连接和事务的构造,还是应该存在于连接内部。
例如:
private void RetryLogSave(DynamicParameters parameters, int retries = 3)
{
int tries = 0;
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
var logItemCommand = new CommandDefinition(commandText: Constants.InsertLogItem,
parameters: parameters, transaction: transaction, commandType: System.Data.CommandType.Text);
do
{
try
{
tries++;
connection.Execute(logItemCommand);
transaction.Commit();
break;
}
catch (Exception exc)
{
if (tries == retries)
{
transaction.Rollback();
throw exc;
}
Task.Delay(100 * tries).Wait();
}
}
while (true);
}
}
}
我在这里所做的是否适当且可接受,或者重试逻辑是否应该存在于 SqlConnection 构造之外?
【问题讨论】:
-
我通常为此使用Polly。事务应该在重试块内。尽量保持你的交易/连接尽可能小
-
@DmitryPavliv 我听说过关于 Polly 的好消息,今天可能会尝试一下。所以,你的建议是交易应该在区块内。那么连接实例化呢?另外,这意味着每次重试都会回滚,对吗?
-
连接应该打开尽可能短的时间。理想情况下,您在 odbc 驱动程序中启用了连接池(这通常是默认设置)。这意味着一旦您关闭连接,它实际上会回到池中,并且另一种方法可以重用它。在重试期间打开连接可能会迫使系统创建过多的物理连接(因为您没有将它们释放回连接池)并耗尽您的 sql server
-
@DmitryPavliv 好的,有道理。
标签: c# transient-failure