【问题标题】:LINQ Select Object based on a property within a list within the objectLINQ 根据对象内列表中的属性选择对象
【发布时间】:2017-06-01 16:33:50
【问题描述】:

我正在尝试根据该对象列表中的属性从对象列表中选择一个对象列表,该对象列表本身具有另一种类型的对象列表。

例如

class TypeA{
  string Name {get; set;}
  List<TypeB> ListOfTypeB {get; set;}
}

class TypeB{
  int Age {get; set;}
  bool Active {get; set;}
}

我有一个由数据库填充的 Type A 列表,我想查询 TypeA 列表并根据 TypeB 中的 Active 属性返回一个 TypeA 列表,该属性是 TypeA 对象中的一个列表。

任何帮助都会很棒。

谢谢

【问题讨论】:

    标签: linq linq-to-entities


    【解决方案1】:

    你写道:

    我想查询 TypeA 的列表并返回一个基于 TypeA 的列表 TypeB 中的 Active 属性。

    这个规范有点不清楚。我假设您的意思是,您希望所有 TypeA 对象至少有一个 TypeB 对象为真值 TypeB.Activity(或那些具有假值的对象)。

    答案取决于您是以Enumerable 还是Queryable 执行查询。一句话:你是想先把对象放入本地内存然后执行查询(AsEnumerable)还是让数据库执行查询(Asqueryable)然后只返回有效结果到本地内存.

    AsEnumerable

    这种方法效率不高,因为这意味着你在处理之前将完整的TypeA和TypeB表放到本地内存中。

    但是您的查询很简单:

    var AwithActivity = allTypeA
        .Where(a => a.ListOfTypeB.Any(b => b.Activity));
    

    一句话:

    typeA 元素的完整序列中,只取那些typeA 元素至少有一个ListOfTypeB 元素的属性Activity 的值为真。

    AsQueryable

    如果您的数据库设置正确,您将拥有两个表。一张包含TypeA 项目的表和一张包含TypeB 项目的表。

    TypeATypeB 具有一对多关系。每个TypeA 有零个或多个TypeB,每个TypeB 恰好属于一个TypeA

    在您的数据库中,TypeATypeB 都有一个主键。每个TypeB 都有一个指向它所属的TypeA 的外键。

    这是相当标准的数据库。它可以帮助您进行查询。使用这些定义,您的查询将被翻译成:

    我想要所有 TypeA 对象,其中至少有一个 TypeB 对象具有此 TypeA 对象的外键和 Activity 的真值

    查询将是:

    var results = TypeATable            // groupjoin table TypeA with table TypeB
        .GroupJoin(TypeBTable,
          typeA => typeA.PrimaryKey,    // from every typeA use the primary key
          typeB => typeB.ForeignKey,    // from every typeB use the foreign key to the TypeA
          (a, allB) => new              // for every A with all matching typeB:
          {                             // create a new anonymous type
             A = a,                     // with the found A
             HasActivity = allB         // and a boolean that says if there was
                .Any(b => b.Activity),  // at least one B with a true Activity
          });
    

    要获得所有具有至少一个活动的 TypeA:

    var AWithActivity = results.Where(result => result.HasActivity)
       .Select(result => result.A);
    

    获取所有没有活动的TypeA:

    var AwithoutActivity = result.Where(result => !result.HasActivity)
       .Select(result => result.A);
    

    加法 如果可能是 typeA 和 typeB 之间的关系不是一对多,而是多对多。在这种情况下,您获取所有活动的 typeB 对象并找到所有具有此活动 typeB 对象的外键的 typeA 对象

    【讨论】:

    • 您好,您是正确的,我重新阅读了我的回复,它有点含糊,我的架构和关系就像您所描述的那样结构良好。我在想的是嵌套选择查询的可能性。感谢您的详细回答,它让我了解了我的 linq 礼仪。
    【解决方案2】:

    这实际上取决于您如何实现过滤器逻辑。如果您想查找类型 A 的列表,其中类型 B 包含至少一个活动标志,那么您可以执行以下操作。

    listOfTypeA.Where(a => a.ListOfTypeB.Any(b => b.Active)).ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 1970-01-01
      相关资源
      最近更新 更多