我正在为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失败,我都会重试(例如,如果它是主键违规则重试是浪费时间),我会立即重试,不会有任何停顿等等。
我的下一步是开始使用Microsoft的Transient Fault Handling库。它包含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;
}
上述最新解决方案被描述为http://blogs.msdn.com/b/appfabriccat/archive/2010/10/28/best-practices-for-handling-transient-conditions-in-sql-azure-client-applications.aspx在SQL Azure客户端应用程序中处理瞬态条件的最佳实践(高级使用模式部分)。
虽然这是向前迈出的一步,但每当我想通过Entity Framework访问数据库时,我仍然需要记住使用RetryPolicy类。在一个由几个人组成的团队中,这是一件容易错过的事情。另外,我认为上面的代码有点乱。
我想要的是一种强制执行重试的方法,始终使用。 Transient Fault Handling库包含一个名为ReliableSQLConnection的类,但我无法找到将其用于Entity Framework的方法。
对这个问题有什么好的建议吗?
答案 0 :(得分:7)
在上述评论之后,Microsoft创建了临时故障处理库,“包括通过ReliableSqlConnection类直接支持使用SQL Azure。”
http://msdn.microsoft.com/en-us/library/hh680899(v=pandp.50).aspx
大多数希望使用Azure的开发人员都会发现上述内容非常有用。
答案 1 :(得分:3)
如果您使用Entity Framework 6(目前处于alpha版本),那么对Azure SQL数据库的瞬态重试有一些新的内置支持(稍加配置):http://entityframework.codeplex.com/wikipage?title=Connection%20Resiliency%20Spec
我创建了一个库,允许您配置实体框架以使用故障处理块重试,而无需更改每个数据库调用 - 通常您只需要更改配置文件,可能需要更改一行或两行代码。
这允许您将它用于实体框架&lt; v6或Linq To Sql。