Повторите запрос LINQ to SQL при временной ошибке - PullRequest
4 голосов
/ 23 августа 2011

Удобно переопределить метод System.Data.Linq.DataContext.SubmitChanges (ConflictMode faultMode), чтобы он повторял попытки в случае временных ошибок, таких как взаимоблокировки или тайм-ауты, при вставке, обновлении или удалении записей.

У меня вопрос: есть ли аналогичная функция, которую можно переопределить для обработки таких ошибок при выполнении запроса LINQ to SQL?Я предполагаю / надеюсь, что в классе DataContext будет метод, который выполняет фактический вызов базы данных и который может быть переопределен для выполнения повторной попытки.

Примеры, которые я видел (например, показанные ниже) обычно оборачивают выражение LINQ и вызов метода, который перечисляет его в блоке повторов:

try
{
    e.Result = retry.ExecuteAction(() =>
        {
            Deadlock(); // Artificially create a deadlock condition

            CustomerOrdersDataContext ctx = new CustomerOrdersDataContext();
            ctx.Connection.ConnectionString = builder.ConnectionString;
            ctx.CommandTimeout = 3;

            var results = from c in ctx.customers
                            from o in c.orders
                            from i in o.order_items
                            select new { c.lname, c.fname, i.product.product_name, i.quantity };

            return results.ToList();
        });
}
catch (SqlException ex)
{
    MessageBox.Show(ex.Message, "SqlException");
}

}

(из http://social.technet.microsoft.com/wiki/contents/articles/retry-logic-for-transient-failures-in-sql-azure.aspx)

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

1 Ответ

0 голосов
/ 17 января 2014

Вы можете сделать это, создав метод расширения, который выполняет повторную попытку за вас:

public static List<T> ToList_DeadlockRetry<T>(this IEnumerable<T> source, int retryAttempts = 5)
{
    while (retryAttempts > 0)
    {
        try
        {
            return source.ToList();
        }
        catch (SqlException ex)
        {
            retryAttempts--;

            if (retryAttempts == 0)
            {
                throw ex;
            }
        }
    }
}

Затем вы можете использовать его следующим образом:

var results = from c in ctx.customers
              from o in c.orders
              from i in o.order_items
              select new { c.lname, c.fname, i.product.product_name, i.quantity };

 return results.ToList_DeadlockRetry();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...