Использование методов Linq для навигации по нескольким объектам Entity Framework с предложением Where

Я пытаюсь сделать запрос по нескольким объектным отношениям, используя объектный запрос.

Цепочка сущностей в основном представляет собой OMRMARKET (один ко многим) СВОЙСТВА (один ко многим) OMRBUILDINGSURVEYS (один ко многим) ПЕРИОДЫ. Или, другими словами, у Рынка много свойств, у свойств много опросов, в опросах много периодов.

Я хочу отфильтровать следующий объектный запрос:

OMRMarketsQuery = OMRMarketsQuery.Include("Properties.OMRBuildingSurveys")

Идентификатор периода (псевдокод) OMRMarket.Properties.OMRBuildingSurveys.PeriodID > 50

Тогда я подумал, что мог бы вложить следующие функции Where, такие как:

OMRMarketsQuery = OMRMarketsQuery.Include("Properties.OMRBuildingSurveys").Where(
Function(m) m.Properties.Where(Function(p) p.OMRBuildingSurveys.Where(Function(s) 
s.PeriodID > 50)))

И я получаю поддержку intellisense, которая помогает мне создать этот запрос, но затем я получаю ошибку

Значение типа "System.Collections.Generic.IEnumerable(Of OMR.OMRInterfaceCustomCode.OMRBuildingSurvey)" не может быть преобразовано в "Boolean"

Любая помощь будет принята с благодарностью. Я знаю, что это должно быть выполнимо. Большое спасибо заранее.

2 ответа

Решение

Хорошо, ответ прост.

Вы не можете фильтровать при использовании Eager Loading или Lazy Loading в этом отношении. Я и несколько фрилансеров перепробовали все виды методов, но ответом было загрузить рынки и свойства, а затем закомментировать следующую строку кода:

'OMRMarketsQuery = OMRMarketsQuery.Include ("Properties.OMRBuildingSurveys")

Чтобы загрузить детали опроса, мы поймали событие изменения списка выбора объектов, и именно здесь мы могли бы выполнить фильтрацию следующим образом:

Private Sub Lbx_PropsByNameSelector_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles Lbx_PropsByNameSelector.SelectionChanged

    Dim propertyAdListBox = CType(sender, ListBox)
    Dim selectedProperty = CType(propertyAdListBox.SelectedItem, OMRInterfaceCustomCode.Property)

    If Not IsDBNull(selectedProperty) Then

        Dim RSurveysQuery = From r In OMRInterfaceEntities.OMRBuildingSurveys Where r.PeriodID > 80 And r.PropertyID = selectedProperty.ID

        Dim RSurveysList = RSurveysQuery.ToList

        If RSurveysList.Any() Then
            Dim RecentSurveysSource = CType(Me.FindResource("OMRMarketsPropertiesOMRBuildingSurveysViewSource"), CollectionViewSource)
            RecentSurveysSource.Source = RSurveysList
        End If
    End If

End Sub

Нам очень трудно "отладить" ваш LinQ без доступа к вашему коду. Тем не менее, когда я пишу сложные LinQ Запросы, я всегда пытаюсь построить каждый последовательный шаг за раз, так что если я получаю сообщение об ошибке, я знаю, что это происходит от последнего бита, который я добавил. Кроме того, обратите пристальное внимание на требуемые типы ввода и возврата LinQ методы, которые вы вызываете.

Например, ваша ошибка говорит о том, что часть вашего запроса ожидает Boolean тип, а не 'System.Collections.Generic.IEnumerable(Of OMR.OMRInterfaceCustomCode.OMRBuildingSurvey) типа... единственное обязательное Boolean значения, которые я вижу в вашем запросе, взяты из Where метод:

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
)

Поэтому я могу только предположить, что часть вашего запроса возвращает коллекцию OMRBuildingSurvey объекты вместо необходимых Func<TSource, bool> сказуемое. Если мы посмотрим на эту часть p.OMRBuildingSurveys.Where(Function(s) s.PeriodID > 50)мы можем видеть, что это вернет IEnumerable из OMRBuildingSurvey экземпляры, которые удовлетворяют условию предиката.

Тем не менее, этот результирующий сбор подается в m.Properties.Where пункт, который также ожидает Func<TSource, bool> предикат... так что, похоже, мы нашли ошибку.

ОБНОВЛЕНИЕ >>>

Хорошо... вопреки моему лучшему суждению, я попробую, слепо, как и я, к структуре ваших классов.

Начиная с правой стороны, мы имеем p.OMRBuildingSurveys.Where(Function(s) s.PeriodID > 50) мы узнали, возвращает IEnumerable из OMRBuildingSurvey экземпляры, которые удовлетворяют условию предиката. Итак, что дальше для этой коллекции?

Нам нужно найти Property объекты, которые содержат любой из этих OMRBuildingSurvey экземпляры:

m.Properties.Where(Function(p) p.OMRBuildingSurveys.Intersect(p.OMRBuildingSurveys.
Where(Function(s) s.PeriodID > 50)).Any())

Я даже не уверен, сработает ли это... то, что мы пытаемся сделать, это вернуть IEnumerable типа Property содержащий предметы, которые имеют какой-либо из OMRBuildingSurvey случаи, которые выполняют PeriodID условие предиката в их OMRBuildingSurveys (CLR) собственность. Intersect метод объединяет значение каждого OMRBuildingSurveys свойство с выходом IEnumerable из OMRBuildingSurvey случаи, которые удовлетворяют условию предиката и Any возвращает все то же самое.

Последний шаг будет примерно таким:

var query = OMRMarketsQuery.Include("Properties.OMRBuildingSurveys").Where(Function(m) 
m.Properties.Intersect(m.Properties.Where(Function(p) p.OMRBuildingSurveys.
Intersect(p.OMRBuildingSurveys.Where(Function(s) s.PeriodID > 50)).Any())).Any())

Я в основном сделал то же самое... использовал предыдущий "запрос пока" в качестве входного параметра для Intersect метод вызывается на OMRBuildingSurvey.Properties имущество. Теперь я надеюсь, что это сработает, потому что у меня больше нет на это времени. Кроме того, VB может быть выключен, потому что я пишу на C#, но я верю, что вы можете дополнить его информацией, которую я предоставил, если этот пример не работает... эти запросы не так уж плохи, когда вы их нарушаете вниз, как я сделал.

Кстати, этот пример соответствует требованию в вашем вопросе, а не в вашем последнем комментарии.

Другие вопросы по тегам