我们最近开始使用 SQL Azure 数据库在 Microsoft Azure 中测试 ASP.NET 应用程序。我们很少会遇到超时和丢失连接的情况。我们现在了解这是基于云的数据库的本质,并且使用 transient 故障处理应用程序 block 是推荐的解决方案。但是,这似乎要求您的代码创建连接并发出访问请求。由于我们使用强类型数据集,因此该逻辑隐藏在 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 错误等时才调用 TransientError
它已经投入生产大约一年了,没有出现任何问题。
关于sql-server - 使用强类型数据集重试 SQL Azure 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35295297/