我正在编写一个针对Windows Azure的应用程序。我正在使用Entity Framework来访问SQL Azure。由于SQL Azure中的限制和其他机制,如果一个SQL语句执行失败,我需要确保我的代码执行重试操作。我正在尝试想出一种可靠的方法来实现这个目标。
(在下面的代码中,ObjectSet返回我的EFContext.CreateObjectSet())
假设我有以下函数:
public Product GetProductFromDB(int productID)
{
return ObjectSet.Where(item => item.Id = productID).SingleOrDefault();
}
现在,这个函数没有重试机制,在SQL Azure中迟早会失败。一个天真的解决方案是像这样做:
public Product GetProductFromDB(int productID)
{
for (int i = 0; i < 3; i++)
{
try
{
return ObjectSet.Where(item => item.Id = productID).SingleOrDefault();
}
catch
{
}
}
}
当然,这种方法也有一些缺点。无论出现什么SQL失败问题(例如主键冲突),我都会进行重试(而重试可能是浪费时间的),我会立即重试而不进行任何暂停等等。
我的下一步是开始使用微软的瞬态错误处理库。它包含RetryPolicy,使我能够将重试逻辑与实际查询代码分开:
public Product GetProductFromDB(int productID)
{
var retryPolicy = new RetryPolicy<SqlAzureTransientErrorDetectionStrategy>(5);
var result = _retryPolicy.ExecuteAction(() =>
{
return ObjectSet.Where(item => item.Id = productID).SingleOrDefault;
});
return result;
}
最新的解决方案描述为一个应用于SQL Azure客户端应用程序中处理瞬态条件的最佳实践,详细信息请参考此处(高级使用模式部分)。虽然这是一种进步,但我仍然需要记得每当想要通过实体框架访问数据库时使用RetryPolicy类。在一个由多个人组成的团队中,这是很容易忽视的事情。此外,上面的代码在我看来有点杂乱无章。
我想要的是一种方法,可以强制始终使用重试。Transient Fault Handling库包含一个名为ReliableSQLConnection的类,但我找不到一种与Entity Framework一起使用的方式。
对此问题有任何好的建议吗?