使用强类型数据集重试 SQL Azure 请求



我们最近开始使用SQL Azure数据库在Microsoft Azure中测试 ASP.NET 应用程序。我们很少超时并失去连接。我们现在明白这是基于云的数据库的本质,建议使用暂时性故障处理应用程序块。但是,这似乎要求代码创建连接并发出访问请求。由于我们使用强类型数据集,因此此逻辑隐藏在 Fill() 中,例如,在为数据集生成的代码中。我们有业务对象单元,它们实际调用生成的代码中的方法,因此我们有一个放置重试逻辑的地方,但宁愿不要在数百个位置放置相同的代码。

在这种情况下,有没有办法使用 TFHAB,或者有办法以不需要太多代码的一般方式合并重试逻辑?

我所做的是我有一个名为 TransientError 的静态类,其中包含以下两个静态方法(我借用了 MSDN 的大部分代码):

internal static void Try(DbContext context)
{
    int wait = 800;
    bool retry = true;
    while (retry)
    {
        try
        {
            using (SqlConnection con = new SqlConnection(context.Database.Connection.ConnectionString))
            {
                con.Open();
                using (SqlCommand com = new SqlCommand("declare @i int;", con))
                {
                    com.ExecuteNonQuery();
                }
            }
            retry = false;
        }
        catch (SqlException)
        {
            Clear(context);
            Thread.Sleep(wait);
        }
        catch (Exception)
        {
            retry = false;
        }
        // break after we reach 6.4 secs (for a total as 12 secs)
        if (wait == 6400)
        {
            retry = false;
        }
        wait = wait * 2;
    }
}
private static void Clear(DbContext context)
{
    // This is a client side operation so won't cause an exception
    // with a server side error.
    // If it does fail, probably should throw!
    using (SqlConnection con = new SqlConnection(context.Database.Connection.ConnectionString))
    {
        SqlConnection.ClearPool(con);
    }
}

这解决了暂时性网络错误在连接池中留下"断开"(且不可重用)连接的问题。

我正在使用 Linq,我的每个访问方法如下所示:

public StructureElement ForId(int elementId)
{
    TransientError.Try(this.context);
    StructureElement element = (from se in this.context.StructureElements
                                where se.Id == elementId
                                select se).FirstOrDefault<StructureElement>();
    return element;
}

使用 TransientError.Try 测试连接(如果出现问题,则会清除 ConnectionPool,然后运行 Linq 查询。如果这有问题,则调用方的异常处理将接管。

其他方法也是可能的 - 仅在实际的 Linq 错误等情况下调用瞬态错误。

它已经投入生产了大约一年,没有任何问题。

最新更新