Использование Entity Framework с SQL Azure - Надежность

Я пишу приложение для 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. Он содержит 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 всякий раз, когда я хочу получить доступ к базе данных через Entity Framework. В команде из нескольких человек это легко пропустить. Кроме того, приведенный выше код немного беспорядочен, по моему мнению.

То, что я хотел бы, это способ принудительного применения повторных попыток всегда использовать все время. Библиотека Transient Fault Handling содержит класс ReliableSQLConnection, но я не могу найти способ использовать его с Entity Framework.

Любые хорошие предложения по этой проблеме?

Ответ 1

После вышеупомянутых замечаний Microsoft создала временную библиотеку обработки ошибок, которая "включает прямую поддержку для работы с SQL Azure через класс ReliableSqlConnection".

http://msdn.microsoft.com/en-us/library/hh680899(v=pandp.50).aspx

Большинство разработчиков, желающих использовать Azure, найдут, что это поможет.

Ответ 2

Если вы используете Entity Framework 6 (в настоящее время в альфа-версии), то есть некоторая новая встроенная поддержка временных повторений с Azure SQL Database (с небольшой конфигурацией): http://entityframework.codeplex.com/wikipage?title=Connection%20Resiliency%20Spec

Я создал библиотеку, которая позволяет настроить Entity Framework на повторную попытку с использованием блока обработки ошибок, не требуя изменения каждого вызова базы данных - обычно вам нужно будет только изменить свой конфигурационный файл и, возможно, одну или две строки кода.

Это позволяет использовать его для Entity Framework < v6 или Linq To Sql.

https://github.com/robdmoore/ReliableDbProvider