Объект Entity Framework, запрос LINQ, проблемы с тайм-аутом

Я попытался изменить свою строку подключения, включив в нее расширенный тайм-аут, и я подтвердил, что на стороне сервера sql представление, которое передает мой объект EF, выполняется в течение нескольких секунд и возвращает в общей сложности 3000 или менее записей.

НО, когда я пытаюсь запустить его с помощью кода, я теперь сталкиваюсь с проблемами тайм-аута, и мне нужен совет, чтобы решить эту проблему. Я получаю сообщение «Истекло время ожидания выполнения. Время ожидания истекло до завершения операции или сервер не отвечает». Большинство решений, которые я нахожу для конкретной ошибки, рекомендуют модификации строки подключения ИЛИ что-то в этом контексте.CommandTimeout... что я не могу понять, как использовать в этой ситуации.

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

Входные аргументы:

  • int? inputSKU = null
  • int? inputStoreNum = null
  • DateTime? inputStartDate = null

Цель состоит в том, чтобы вернуть полный список.

И зависает, потому что пропускает все условные биты: var qUniqueOffers = query.GroupBy(q => q.Plan_Number).ToList();

Спасибо.


private List<PromotionItem> QueryPromotion(int? inputSKU, int? inputStoreNum, DateTime? inputStartDate)
{
    log.Info("Client requested QueryPromotion");
    List<PromotionItem> resultQuery = new List<PromotionItem>();

    try
    {
        using (DWH_Entities db = new DWH_Entities())
        {
            var query = db.vw_Web_Promotion.AsQueryable();

            // filter promotion results that don't match SKU#
            if (inputSKU != null)
                query = query.Where(q => q.Sku_Number == inputSKU);
            // filter promotion results that don't match Store Num
            if (inputStoreNum != null)
                query = query.Where(q => q.Store_Number == inputStoreNum);
            // filter promotion results that don't match Promotion Start Date
            if (inputStartDate != null)
                query = query.Where(q => q.Start_Date >= inputStartDate);
            // Group promotions By Plan Number ('Promotion ID')
            var qUniqueOffers = query
                                .GroupBy(q => q.Plan_Number)
                                .ToList();
            // Select first from each group to get unique details
            var qOffers = qUniqueOffers
                        .Select(g => g.OrderBy(gi => gi.Plan_Number).First())
                        .ToList();

            foreach (var qo in qOffers)
            {
                resultQuery.Add(new PromotionItem
                {
                    PromotionNumber = qo.Plan_Number.Trim(),
                    PromotionDescription = qo.Plan_Description.Trim(),
                    StartDate = qo.Start_Date,
                    EndDate = qo.End_Date
                });
            }
        }
    }
    catch (Exception e)
    {
        log.Error("[" + e.TargetSite + "] | " + e.Message);
        throw e;
    }

    return resultQuery;
}

person OldMan    schedule 22.06.2017    source источник
comment
Какая строка генерирует исключение Execution Timeout Expired? Можете ли вы показать нам его скриншот?   -  person mjwills    schedule 22.06.2017
comment
@mjwills в отношении этого блока кода. Строка 22. Он попадает в точку останова, которую я установил там, и когда я продолжаю, он срабатывает в течение 30 секунд или около того, а затем выдает исключение тайм-аута. var qUniqueOffers = query.GroupBy(q => q.Plan_Number).ToList();   -  person OldMan    schedule 22.06.2017
comment
TejasVaishnav опубликовал решение, которое увеличило время ожидания, но, к сожалению, я считаю, что мой запрос/приложение не так оптимизировано, как могло бы быть, поскольку оно все еще истекает через 300 секунд. попробую переписать.   -  person OldMan    schedule 22.06.2017
comment
Что произойдет, если вы удалите ToList из var qUniqueOffers = query .GroupBy(q => q.Plan_Number) .ToList()? Это улучшает ситуацию?   -  person mjwills    schedule 22.06.2017
comment
@mjwills знаешь что. Думаю, это помогло. Спасибо большое.   -  person OldMan    schedule 22.06.2017


Ответы (2)


// Group promotions By Plan Number ('Promotion ID')
var qUniqueOffers = query
                    .GroupBy(q => q.Plan_Number)
                    .ToList();
// Select first from each group to get unique details
var qOffers = qUniqueOffers
            .Select(g => g.OrderBy(gi => gi.Plan_Number).First())
            .ToList();

То, как вы написали приведенный выше LINQ, означает, что вы получаете много данных по сети (первый ToList), а затем получаете подмножество данных (используя First и второй ToList). Попробуйте изменить его на:

// Group promotions By Plan Number ('Promotion ID')
var qUniqueOffers = query
                    .GroupBy(q => q.Plan_Number)
// Select first from each group to get unique details
var qOffers = qUniqueOffers
            .Select(g => g.OrderBy(gi => gi.Plan_Number).First())
            .ToList();

Это должно привести к тому, что из базы данных будет отправляться намного меньше данных, что, как мы надеемся, ускорит ее.

Как указано в https://stackoverflow.com/a/13827077/34092:

ToList() всегда заставляет все, что находится перед ним, немедленно оценивать, в отличие от отложенного выполнения.

person mjwills    schedule 22.06.2017
comment
mjwills спасибо за подробный ответ. Я добавлю, что в результате мне пришлось изменить .First() на .FirstorDefault(), потому что это вызывало синтаксическое исключение. - person OldMan; 24.06.2017

Если вы используете последнюю версию EF, выполните следующие действия, чтобы увеличить время ожидания:

using (DWH_Entities db = new DWH_Entities())
{
    db.Database.CommandTimeout = 300;
    ...

Если вы хотите записи в минимальное время, попробуйте следующее:

var temp = query.ToList();
var qUniqueOffers = temp.GroupBy(q => q.Plan_Number)
                                .ToList();
person Tejas Vaishnav    schedule 22.06.2017
comment
Теджас Вайшнав Спасибо. Использование EF6, и это помогает ответить на мой первоначальный вопрос о продлении времени ожидания. Мне пришлось изменить контекст на db из-за значения, которое я присвоил своему объекту, но это увеличило время выполнения db.Database.CommandTimeout = 300; - person OldMan; 22.06.2017
comment
Моя ошибка, отредактировано для других, спасибо, что сообщили об этом - person Tejas Vaishnav; 22.06.2017
comment
Я не знаю, почему вы не получаете любви к этому ответу. db.Database.CommandTimeout работал. Так много людей из-за сложных ответов, ваш идеален. Продолжайте хорошую работу. Хорошего дня, сэр. - person Chris; 01.08.2017