Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Azure高效实现上LINQ-TO-SQL的重试逻辑?_Linq To Sql_Azure Sql Database - Fatal编程技术网

SQL Azure高效实现上LINQ-TO-SQL的重试逻辑?

SQL Azure高效实现上LINQ-TO-SQL的重试逻辑?,linq-to-sql,azure-sql-database,Linq To Sql,Azure Sql Database,我有一个相当大的web应用程序在Azure中运行,使用LINQ-TO-SQL,我遇到了来自SQLAzure的暂时错误,因此需要实现重试。我知道和一些网站给出了如何使用它的示例,但看起来您必须将每个LINQ查询封装在类似的内容中: RetryPolicy retry = new RetryPolicy<MyRetryStrategy>(5, TimeSpan.FromSeconds(5)); Result = retry.ExecuteAction(() => { … LI

我有一个相当大的web应用程序在Azure中运行,使用LINQ-TO-SQL,我遇到了来自SQLAzure的暂时错误,因此需要实现重试。我知道和一些网站给出了如何使用它的示例,但看起来您必须将每个LINQ查询封装在类似的内容中:

RetryPolicy retry = new RetryPolicy<MyRetryStrategy>(5, TimeSpan.FromSeconds(5));
Result = retry.ExecuteAction(() =>
{
   … LINQ query here...
});
RetryPolicy retry=new RetryPolicy(5,TimeSpan.FromSeconds(5));
结果=重试。执行操作(()=>
{
…这里是LINQ查询。。。
});
在我的数据层中有数百个LINQ查询,这看起来真的很混乱,再加上一个事实,在枚举结果之前,很多时候查询实际上都没有执行。例如,我的数据层中的大多数函数都将IQueryable返回到业务层(这使它们比返回列表更灵活)。因此,这意味着您必须在业务逻辑层中添加数据库重试逻辑-丑陋

因此,我想为了在数据层中保留重试逻辑,我必须在所有查询中添加.ToList(),以便它们就在那里执行,而不是在上面的层中执行

我真希望有一种方法可以在一些基类中实现重试逻辑,而不必更改所有查询。似乎EF也会有这个问题


是尝试说服SQL Azure团队进行自动重试的真正答案,因此我们不必在代码中担心这一点?

我不知道有什么好的解决方案,因为LINQ to SQL不允许我们拦截查询。但是一点代码重构可能会有所帮助。类似于(伪代码):

公共结果查询WithRetry(IQueryable查询)
{
RetryPolicy retry=新的RetryPolicy(5,TimeSpan.FromSeconds(5));
(() => 
{ 
返回retry.ExecuteAction(查询);
}
}
现在调用此方法稍微容易一些:

结果=QueryWithRetry(…此处为LINQ查询…)

但是,仍然需要修改代码并更改每个查询

致以最良好的祝愿


徐明。

在需要实现类似的功能后,我继续将其打造成一个库:(麻省理工学院授权并在NuGet上提供)

您可以通过编写
SubmitChangesRetry()
来重试
SubmitChanges()
调用:

using(var context = new MyDbContext())
{
  context.Items.InsertOnSubmit(new Item { Name = "ABC" });
  context.SubmitChangesRetry();
}
您还可以使用
retry()
扩展方法重试查询:

using(var context = new MyDbContext())
{
  int count = context.Items.Where(x => x.Name == "ABC").Retry().Count();
}
具体的重试逻辑由策略控制。在引擎盖下,重试机制如下所示:

int retryCount = 0;
while (true)
{
    try
    {
        return func();
    }
    catch (Exception ex)
    {
        TimeSpan? interval = retryPolicy.ShouldRetry(retryCount, ex);
        if (!interval.HasValue)
        {
            throw;
        }
        Thread.Sleep(interval.Value);
    }
    retryCount++;
}

了解调用
func()中的函数
retryPolicy
对象是根据使用情况提供的。这只是让您了解重试循环期间发生的情况。只需查看存储库中的详细信息。

这会有一点帮助,但我是否仍需要担心直到稍后在枚举查询的代码中才会执行的查询?因此,我必须真正调查每个查询,并找出数据库的实际调用位置。对不起,我不能很好地理解您。您的意思是说,您担心如果出现问题,将很难找到问题的根源,因为查询被包装在重试框架中?在这种情况下,我会这样做我建议您在retry.ExecuteAction上设置一个断点,然后逐步完成代码。不,我的意思是将重试逻辑添加到具有数百个查询的现有应用程序将是一项困难的任务-主要是因为数据库调用不一定发生在数据层的linq to sql查询中。查询的执行可能会延迟到l IQueryable实际上是枚举的-这可能发生在业务层。对于这个问题似乎没有一个干净的解决方案。我不知道有更好的解决方案。实际上,即使在连接到本地数据库时,也建议使用重试逻辑。如果我们以前实现过重试逻辑,这将非常容易r将我们的项目迁移到SQL Azure。重试逻辑不是SQL Azure特有的。这是我们希望连接到数据库并使解决方案健壮时的最佳做法。
int retryCount = 0;
while (true)
{
    try
    {
        return func();
    }
    catch (Exception ex)
    {
        TimeSpan? interval = retryPolicy.ShouldRetry(retryCount, ex);
        if (!interval.HasValue)
        {
            throw;
        }
        Thread.Sleep(interval.Value);
    }
    retryCount++;
}