Linq Проверка пустого подзапроса без попадания в удаленную базу данных. - PullRequest
2 голосов
/ 23 марта 2012

У меня есть подзапрос linq:

        for (int i = 0; i < parentAttributes.Length; i++)
        {
            Guid parent = parentAttributes[i];
            var subQuery = from sc in db.tSearchCluendexes
                           join a in db.tAttributes on sc.AttributeGUID equals a.GUID
                           join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID
                           where a.RelatedGUID == parent && userId == pc.CPSGUID                             
                           select sc.CPSGUID;

            query = query.Where(x => subQuery.Contains(x.Id));
        }

Основная идея состоит в том, что я фильтрую список данных (представленных переменной запроса) на основе результатов подзапроса, выполненного неопределенное количество раз.

Однако теперь у меня есть проблема, из-за которой я хочу выполнять запрос where только в том случае, если подзапрос действительно содержит данные, и я не хочу выполнять подзапрос в каждой итерации цикла (например, с помощью Count ( ) или ToList ()), поскольку это поразит удаленный ресурс. Примерно так, как показано ниже, если мы примем, что метод HasData () на самом деле возвращает true или false:

        for (int i = 0; i < parentAttributes.Length; i++)
        {
            Guid parent = parentAttributes[i];
            var subQuery = from sc in db.tSearchCluendexes
                           join a in db.tAttributes on sc.AttributeGUID equals a.GUID
                           join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID
                           where a.RelatedGUID == parent && userId == pc.CPSGUID                             
                           select sc.CPSGUID;

            if (subQuery.HasData())                
               query = query.Where(x => subQuery.Contains(x.Id));
        }

Предложения приветствуются.

Ответы [ 2 ]

4 голосов
/ 23 марта 2012

Ваши предложения по использованию Count и ToList не самый быстрый способ узнать, есть ли у запроса какие-либо результаты.Вы должны использовать метод Any:

if (subQuery.Any())
{            
   query = query.Where(x => subQuery.Contains(x.Id));
}

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

query = query.Where(x => !subQuery.Any() || subQuery.Contains(x.Id));
0 голосов
/ 26 марта 2012

После некоторой очень подробной проверки ответа Марка я могу подтвердить, что Any () должен быть в лямбда-выражении, так как в противном случае код будет делать вызов непосредственно в базу данных во время каждой итерации цикла (не желательно).

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

        for (int i = 0; i < parentAttributes.Length; i++)
        {
            Guid parent = parentAttributes[i];
            var subQuery = from sc in db.tSearchCluendexes
                           join a in db.tAttributes on sc.AttributeGUID equals a.GUID
                           join pc in db.tPeopleCluendexes on a.GUID equals pc.AttributeGUID
                           where a.RelatedGUID == parent && userId == pc.CPSGUID                             
                           select sc.CPSGUID;


            query = query.Where(x => !subQuery.Any() || subQuery.Contains(x.Id));                
        }

Этот код объединяет серию существующих операторов в sql, которые в конечном итоге будут вызваны на более позднем этапе процесса. Если у вас есть Any () вне лямбды, то эти SQL-запросы вызываются по отдельности.

Еще раз спасибо, Марк - лучший человек.

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