将实体框架与 SQL Azure 结合使用 - 可靠性
我正在为 Windows Azure 编写一个应用程序。我正在使用实体框架访问 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 的瞬态故障处理库。它包含 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 客户端应用程序中处理瞬态条件的最佳实践(高级使用模式部分)。
虽然这是向前迈出的一步,但每当我想通过实体框架访问数据库时,我仍然必须记住使用 RetryPolicy 类。在几个人的团队中,这是很容易忽略的事情。另外,我认为上面的代码有点混乱。
我想要的是一种强制始终使用重试的方法。瞬态故障处理库包含一个名为 ReliableSQLConnection 的类,但我找不到将其与实体框架一起使用的方法。
对于这个问题有什么好的建议吗?
I'm writing an application for Windows Azure. I'm using Entity Framework to access SQL Azure. Due to throttling and other mechanisms in SQL Azure, I need to make sure that my code performs retries if an SQL statement has failed. I'm trying to come up with a solid method to do this.
(In the code below, ObjectSet returns my EFContext.CreateObjectSet())
Let's say I have a function like this:
public Product GetProductFromDB(int productID)
{
return ObjectSet.Where(item => item.Id = productID).SingleOrDefault();
}
Now, this function performs no retries and will fail sooner or later in SQL Azure. A naive workaround would be to do something like this:
public Product GetProductFromDB(int productID)
{
for (int i = 0; i < 3; i++)
{
try
{
return ObjectSet.Where(item => item.Id = productID).SingleOrDefault();
}
catch
{
}
}
}
Of course, this has several drawbacks. I will retry regardless of SQL failure (retry is waste of time if it's a primary key violation for instance), I will retry immediately without any pause and so on.
My next step was to start using the Transient Fault Handling library from Microsoft. It contains RetryPolicy which allows me to separate the retry logic from the actual querying code:
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;
}
The latest solution above is described as a http://blogs.msdn.com/b/appfabriccat/archive/2010/10/28/best-practices-for-handling-transient-conditions-in-sql-azure-client-applications.aspx Best Practices for Handling Transient Conditions in SQL Azure Client Application (Advanced Usage Patterns section).
While this is a step forward, I still have to remember to use the RetryPolicy class whenever I want to access the database via Entity Framework. In a team of several persons, this is a thing which is easy to miss. Also, the code above is a bit messy in my opinion.
What I would like is a way to enforce that retries are always used, all the time. The Transient Fault Handling library contains a class called ReliableSQLConnection but I can't find a way to use this with Entity Framework.
Any good suggestions to this issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在上述言论之后,微软创建了瞬态故障处理库,其中“包括通过 ReliableSqlConnection 类使用 SQL Azure 的直接支持”。
http://msdn.microsoft.com/en-us/library/hh680899 (v=pandp.50).aspx
大多数希望使用 Azure 的开发人员都会发现上述内容有很大帮助。
After the above remarks, Microsoft created the transient fault handling library, which "includes direct support for working with SQL Azure through the ReliableSqlConnection class."
http://msdn.microsoft.com/en-us/library/hh680899(v=pandp.50).aspx
Most developers looking to use Azure will find the above to be of great help.
如果您使用 Entity Framework 6(目前处于 alpha 版本),则有一些新的内置支持对 Azure SQL 数据库的瞬时重试(需要一些配置):http://entityframework.codeplex.com/wikipage?title=Connection%20Resiliency%20Spec
我创建了一个库,允许您配置实体框架以重试使用故障处理块,而无需需要更改每个数据库调用 - 通常您只需要更改配置文件和可能的一两行代码。
这允许您将它用于实体框架< v6 或 Linq To Sql。
https://github.com/robdmoore/ReliableDbProvider
If you use Entity Framework 6 (currently in alpha) then there is some new in-built support for transient retries with Azure SQL Database (with a little bit of configuration): http://entityframework.codeplex.com/wikipage?title=Connection%20Resiliency%20Spec
I've created a library which allows you to configure Entity Framework to retry using the Fault Handling block without needing to change every database call - generally you will only need to change your config file and possibly one or two lines of code.
This allows you to use it for Entity Framework < v6 or Linq To Sql.
https://github.com/robdmoore/ReliableDbProvider