Как получить LINQ top (1) при доступе к связанным сущностям?.Take () и .FirstOrDefault () не работают? - PullRequest
3 голосов
/ 03 июня 2011

Использование LINQ для сущностей с Entity Framework и C #:

У меня есть метод, который называется CanInactivateReason, который проверяет отсутствие активных связанных записей, прежде чем разрешить пользователю инактивировать причину.Если метод возвращает значение false, то отображается изображение «DisabledDelete» со всплывающей подсказкой, информирующей пользователя, почему он не может удалить объект в сетке, вместо кнопки «Удалить».Моя проблема заключается в производительности, когда запросы возвращают все связанные объекты вместо того, чтобы делать топ 1 для каждого свойства навигации.

. Метод расширения .Take (1) не добавляет топ (1) в мой запрос LINQ to Entities -почему ??

Также .Count ()> 0 или .Any () или .Take (1) .ToArray (). Any () или .FirstOrDefault ()! = null

Вот мой метод, который возвращает bool, поэтому я бы предпочел, чтобы запросы были топ-1 - я попробовал каждый элемент ниже:

    public bool CanInactivateReason(Reason reasonToInactivate)
    {
        bool canInactivate = true;

        if (reasonToInactivate.ProductReasons.Select(pa => pa).Where(pa => pa.Inactive == false).Count() > 0)
        {
            canInactivate = false; // Still active products associated
        }

        if (reasonToInactivate.EnhancementReasons.Select(ea => ea).Where(ea => ea.Inactive == false).Any())
        {
            canInactivate = false; // Still active enhancements associated
        }

        if (reasonToInactivate.SuggestionReasons.Select(sa => sa).Where(sa => sa.Inactive == false).Take(1).ToArray().Any())
        {
            canInactivate = false; // still active suggestions associated
        }

        if ((reasonToInactivate.SessionProductReasons.Select(spr => spr).Where(spr => spr.Inactive == false).FirstOrDefault()) != null)
        {
            canInactivate = false; // Still active sessions associated
        }
        return canInactivate;
    }

Я предполагаю, что это связано с доступом к связанным объектам моего объекта, но чтоя могу сделать, чтобы превратить эти запросы в сгенерированный SQL top (1)?

Заранее спасибо!

1 Ответ

1 голос
/ 03 июня 2011

Работа с такими свойствами навигации может вызвать проблемы. Зависит от того, как вы настроили LazyLoading, какова ваша базовая модель (например, использование ассоциаций наследования) и каков базовый запрос для reasonToInactivate.

В качестве отправной точки я бы посоветовал вернуться к основам с запросом - просто чтобы доказать концепцию.

Так что-то вроде (в зависимости от вашей схемы):

if(context.SuggestionReasonsEntitySet.Any(p => p.ReasonId == reasonToActivateId && p.IsActive)) 
{
    canInactivate = false; // Still active enhancements associated
}

Итак, полностью измените свойство навигации. Навигационные свойства могут быть хорошими, но они также могут скрывать простые запросы. Лично я придерживаюсь их для запросов выбора (т. Е. Чтобы избежать необходимости выполнять объединения при создании проекции), но избегаю их для фильтрации логики - просто потому, что меня несколько раз укусили, как при использовании ассоциаций наследования.

Если это сработает, вы можете попытаться вернуться к своему решению для свойств навигации, чтобы найти точку, в которой что-то пойдет не так.

Если это бесполезно - достаточно ли сгенерированный SQL из ваших запросов выше, чтобы публиковать (и понимать)? Если это так, вы можете опубликовать это?

...