【问题标题】:Linq to Entities - Filter on any item in one list belonging to another listLinq to Entities - 过滤一个列表中属于另一个列表的任何项目
【发布时间】:2015-05-01 20:39:08
【问题描述】:

这是我的场景。我有一个文档类。文档通过多对多关系与 DocumentClasses 表相关联,因此文档可以有一个或多个类。运行搜索时,用户可以选择按类别过滤文档。因此,如果用户选择选择任何类,我需要能够将 where 子句附加到我的查询中。逻辑是,如果文档被分配给用户选择的类中的任何类,则应该返回该文档。所以伪代码中需要的基本查询。所以基本上,如果列表 A 中的任何数字属于列表 B,则返回记录。

我已经尝试过了(RestrictByClasses 只是一个 List(Of Integer)):

query = query.where(Function(resultItem) RestrictByClasses.Contains(resultItem.DocumentClassIds.Any())

但我得到以下异常:

The nested query is not supported. Operation1='Case' Operation2='Collect'

有没有办法让 linq 像这样过滤记录?

谢谢!

更新:

在进行了更多调试之后,我认为这更多地与我如何投影到对象上有关,以便使用可用于过滤的值加载它。这是我进行投影的方式:

Dim query = From document In dbContext.Documents
                        Select New FeeAndReceptionReportIntermediateItem With
                                 {
                                     .BookTypeId = If(restrictByBookTypes AndAlso document.DocumentInstruments.Any(), document.DocumentInstruments.FirstOrDefault().Instrument.BookTypeId, Nothing),
                                     .CustomerId = document.CustomerId,
                                     .DocumentClassIds = If(restrictByDocumentClasses, document.DocumentClasses.Select(Function(group) group.ClassId), Nothing),
                                     .DocumentId = document.DocumentId,
                                     .DocumentNumber = document.DocumentNumber,
                                     .DepartmentId = document.DepartmentId,
                                     .InstrumentGroupIds = If(restrictByInstrumentGroup, document.DocumentInstruments.FirstOrDefault().Instrument.InstrumentGroups.Select(Function(group) group.InstrumentGroupId), Nothing),
                                     .RecordDateTime = document.RecordDateTime,
                                     .RestrictedInstrument = (includeRestrictedDocuments AndAlso document.DocumentInstruments.Any() AndAlso document.DocumentInstruments.FirstOrDefault().Instrument.Restricted)
                                 }

我认为它在抱怨 .DocumentClassIds 和 .InstrumentGroupId 是如何加载到 POCO 对象 (FeeAndReceptionReportIntermediateItem) 中的。我真的很想在初始查询中加载这些,在调用 .ToList() 之前,如果用户没有通过要求我创建连接的限制,我真的不想进行连接,这就是为什么我在加载这些集合时使用导航属性和 if 语句的原因,因为我假设如果“restrictByDocumentClasses”为 false,则不会访问导航属性并且不会包含连接。

【问题讨论】:

    标签: linq linq-to-entities


    【解决方案1】:

    这是一种通用模式。第一行从 DbSet 获取一个 IQueryable。 select 为我们完成了这项工作,因此我们可以在构建查询时继续重用查询来保存查询。然后继续添加 If...Then...query=query.Where(...)...Endif 以继续缩减结果集。

    var query=db.MyTable.Select(x=>x);
    
    if (RestrictByClasses.Any())
      query=query.Where(r => 
        r.DocumentClasses.Select(x=>x.ClassId)
        .Intersect(RestrictByClasses)
        .Any());
    
     if (RestrictBySomethingElse)
       query=query.Where(x=>SomethingElse)
    

    我认为这是 VB.NET 中的等价物:

    Dim query = db.MyTable.[Select](Function(x) x)
    
    If RestrictByClasses.Any() Then
        query = query.Where(Function(r) r.DocumentClasses.Select(Function(group) group.ClassId).Intersect(RestrictByClasses).Any())
    End If
    
    'Repeat as necessary
    If RestrictBySomethingElse Then
        query = query.Where(Function(x) SomethingElse)
    End If
    'End repeat
    
    ' Rest here is pseudo code
    ' Sort
    SELECT/SWITCH sortonfield
    CASE 'name': query=query.OrderBy(Function(x) x.name)
    CASE 'dob': query=query.OrderBy(Function(x) x.dob)
    DEFAULT: query=query.OrderBy(Function(x) x.id)
    END CASE
    
    'Paginate
    query=query.Skip((pagenumber-1)*pagesize).Take(pagesize)
    
    'Project
    Dim finalresult=query.Select(Function(x) new something {
      name=x.Name,
      id=x.id,
      things=x.things
     });
    

    一旦你的所有过滤器都已经到位(以及可选的排序和分页),然后将你的结果集投影到你需要的任何地方。

    【讨论】:

    • 这可能是正确的语法,但我仍然得到同样的错误。我想我需要将查询投影到一个对象,然后将 where 条件添加到第二个 linq to objects 查询。直到下周我才能确定这是否有效(即使我克服了错误也会返回正确的数据),但我会回来更新你。感谢您的回答,我希望这是我需要的。
    • 是的,我仍然收到与此语句相同的错误。无赖。
    • @DonnieDarko 更改了答案以显示如何进行选择性过滤,如果不需要过滤,则绕过连接。
    • 我想我的 POCO 对象的投影已经解决了。我必须实际在查询中进行连接,而不是使用导航属性。我真的不喜欢这样,因为如果我不需要,我不想做连接但是..
    • 我真的只在这行之后:query = query.Where(Function(r) r.DocumentClasses.Select(Function(group) group.ClassId).Intersect(RestrictByClasses).Any()) .我认为这可能会奏效,而且我确实喜欢使用 Intersect,我想研究一下,看看我是否可以以某种方式使用它。我认为我的主要错误只是由于我的投影方式,与我的 .where 没有任何关系。
    猜你喜欢
    • 2015-06-04
    • 2012-03-03
    • 2012-06-30
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    相关资源
    最近更新 更多