使用Linq方法使用Where子句导航多个实体框架实体

时间:2013-09-03 08:50:17

标签: wpf entity-framework linq-to-entities objectquery

我正在尝试使用对象查询查询多个实体关系。

实体链基本上是OMRMARKET(一对多)属性(一对多)OMRBUILDINGSURVEYS(一对多)PERIODS。或者换句话说,市场有很多属性,属性有很多调查,调查有很多期间。

我想过滤以下对象查询:

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

关于期间ID(伪代码)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 个答案:

答案 0 :(得分:0)

我们很难在不访问您的代码的情况下“调试”您的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),我们可以看到这将返回满足谓词条件的IEnumerableOMRBuildingSurvey个实例。

但是,这个产生的集合正在被提供给m.Properties.Where子句,它也期望Func<TSource, bool>谓词...所以我们似乎找到了错误。

更新&gt;&gt;&gt;

好的...反对我更好的判断,我会给你一个机会,因为我对你班级的结构视而不见。

从右侧开始,我们已经p.OMRBuildingSurveys.Where(Function(s) s.PeriodID > 50)我们学会了返回满足谓词条件的IEnumerableOMRBuildingSurvey个实例。那么这个系列的下一步是什么?

我们需要查找包含任何Property个实例的OMRBuildingSurvey个对象:

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

我甚至不确定这个是否会起作用...我们在这里尝试做的是返回包含项目的IEnumerable类型Property具有在OMRBuildingSurvey(CLR)属性中满足PeriodID谓词条件的任何OMRBuildingSurveys个实例的任何实例。 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#而被“关闭”,但我相信如果此示例不起作用,您可以使用我提供的信息来完成此操作...这些查询不是'当你像我一样打破它们时,它会如此糟糕。

  

顺便说一句,此示例遵循问题中的要求,而不是最后的评论

答案 1 :(得分:0)

好的答案很简单。

在使用“预先加载”或“延迟加载”时,您无法进行过滤。我自己和几个自由职业者尝试了各种方法,但答案是加载市场和属性,然后注释掉以下代码:

'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