首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对于捕获SQLException和重试,什么是好的C#编码风格

对于捕获SQLException和重试,什么是好的C#编码风格
EN

Stack Overflow用户
提问于 2011-01-28 04:46:43
回答 8查看 17.2K关注 0票数 19

我有一个方法,它调用SQLServer函数对表执行自由文本搜索。该函数偶尔会在第一次调用时导致SQLException:“全文查询字符串的断字超时”。因此,通常我希望重试该请求,因为它将在后续请求中成功。什么是构建重试逻辑的好风格。目前我有以下几点:

代码语言:javascript
复制
var retryCount = 0;
var results = new List<UserSummaryDto>();
using (var ctx = new UsersDataContext(ConfigurationManager.ConnectionStrings[CONNECTION_STRING_KEY].ConnectionString))
{
    for (; ; )
    {
        try
        {
            results = ctx.SearchPhoneList(value, maxRows)
                         .Select(user => user.ToDto())
                         .ToList();
            break;
        }
        catch (SqlException)
        {
            retryCount++;
            if (retryCount > MAX_RETRY) throw;
        }
    }
}

return results;
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2011-01-28 07:00:44

感谢所有的反馈。我自己回答这个问题,这样我就可以从给出的答案中吸收一些元素。如果我遗漏了什么,请告诉我。我的方法变成:

代码语言:javascript
复制
var results = new List<UserSummaryDto>();
Retry<UsersDataContext>(ctx => results = ctx.SearchPhoneList(value, maxRows)
                                            .Select(user => user.ToDto())
                                            .ToList());
return results;

为了重用,我重构了原始的方法。仍然有很多层次的嵌套。它还依赖于数据上下文的默认构造函数,这可能过于严格。@Martin,我考虑包括你的PreserveStackTrace方法,但在这种情况下,我不认为它真的增加了足够的价值-很好地知道以供将来参考,谢谢:

代码语言:javascript
复制
private const int MAX_RETRY = 2;
private const double LONG_WAIT_SECONDS = 5;
private const double SHORT_WAIT_SECONDS = 0.5;
private static readonly TimeSpan longWait = TimeSpan.FromSeconds(LONG_WAIT_SECONDS);
private static readonly TimeSpan shortWait = TimeSpan.FromSeconds(SHORT_WAIT_SECONDS);
private enum RetryableSqlErrors
{
    Timeout = -2,
    NoLock = 1204,
    Deadlock = 1205,
    WordbreakerTimeout = 30053,
}

private void Retry<T>(Action<T> retryAction) where T : DataContext, new()
{
    var retryCount = 0;
    using (var ctx = new T())
    {
        for (;;)
        {
            try
            {
                retryAction(ctx);
                break;
            }
            catch (SqlException ex)
                when (ex.Number == (int) RetryableSqlErrors.Timeout &&
                      retryCount < MAX_RETRY)
            {
                Thread.Sleep(longWait);
            }
            catch (SqlException ex)
                when (Enum.IsDefined(typeof(RetryableSqlErrors), ex.Number) &&
                      retryCount < MAX_RETRY)
            {
                Thread.Sleep(shortWait);
            }
            retryCount++;
        }
    }
}
票数 12
EN

Stack Overflow用户

发布于 2011-01-28 04:49:43

我将异常处理更改为仅在某些错误上重试:

  • 1204,1205 deadlocks
  • -2 \f25 timeout
  • -1 \f25 connection broken

-1\f6(连接1204,1205-2\f25 timeout-2\f6超时和断开连接)-2\f6

这些是基本的“可重试”错误

代码语言:javascript
复制
catch (SqlException ex)
{
    if !(ex.Number == 1205 || ex.Number == 1204 || ... )
    {
        throw
    }
    retryCount++;
    if (retryCount > MAX_RETRY) throw;
}

编辑,我完全忘记了等待,这样你就不会敲击SQL框:

  • Add a 500 ms wait on deadlock
  • Add a 5 sec delay on timeout

编辑2:

我是一个开发者数据库管理员,不会做太多的C#。我的回答是纠正调用的异常处理...

票数 17
EN

Stack Overflow用户

发布于 2011-07-04 17:04:28

我的sql可重试枚举如下所示:

代码语言:javascript
复制
SqlConnectionBroken = -1,
SqlTimeout = -2,
SqlOutOfMemory = 701,
SqlOutOfLocks = 1204,
SqlDeadlockVictim = 1205,
SqlLockRequestTimeout = 1222,
SqlTimeoutWaitingForMemoryResource = 8645,
SqlLowMemoryCondition = 8651,
SqlWordbreakerTimeout = 30053
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4821668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档