c# - LINQ Group By 如果一个对象有 x 个属性,则在每个组上进行选择

标签 c# linq

我有一些使用 LINQ 的经验,但事实证明编写这个查询有点超出我的能力范围。

请原谅我的伪代码...

class Person{
Collection<Communications> {get;set}
}

class Communication{
Collection<PersonSender> {get;set;}
Collection<BuildingSender> {get;set;}
}

class PersonSender{
Collection<Posts> {get;set}
}

class BuildingSender{
Collection<Posts> {get;set}
}

我想要完成的任务:Communication 分组是否包含 PersonSender 实例的集合或BuildingSender当这些实例有 Post 时实例本身。

然后我想对Collection的每组执行选择查询对象,这样我就可以返回 IEnumerable另一个对象的集合Package使用每个 Collection 在 select 语句中创建的的属性。 这里的关键是我需要对返回的每个组执行单独的选择语句

这是迄今为止我得到的实际查询

m.Communications.GroupBy(x => 
new {fromMember = (x.PersonSender.Any() && x.Posts.Any()), 
     fromBuilding = (x.BuildingSender.Any() && x.Posts.Any())})
    .Select(u => new Package(u.PersonSender.First().Member,u.Posts.First()));

但是我很确定这不会编译,并且它不会为我提供我需要的多个选择语句。

GroupBy 是解决这个问题的正确方法吗?这可能吗?

更新:根据@Hogan,我已经能够拼凑出一个工作解决方案。让我试着弄清楚我想要做什么,我原来的问题不是很清楚......

此代码是类 PackageFactory 的一部分。此类中的每个方法都可以由我的应用程序中的 Controller 调用,要求一组 Package对象。 Package接受多种类型的 IEntity对象作为参数并包装与 IEntity 关系关联的内容。对象已进入一个接口(interface),任何其他在我的应用程序上显示信息的 Controller 都可以读取该接口(interface)。总而言之 Package是一个美化的适配器模式设计对象。

PackageFactory中的每个方法负责查询Communication存储库,查找相关Communication具有正确属性集的对象,然后将对象子集(即 Communication 对象的属性)传递给新的 Package返回整组 Package 之前要包装的实例对象到 Controller ,以便它们可以呈现在页面上。

就我为这个问题编写的方法而言,用户 m收藏了Communication每个 Communication 的对象来自IEntity指向用户 PersonSender 的对象( BuildingSenderm ) 。我的查询是试图隔离 Communication对象分成两组,其中一组包含所有 Communication哪里PeronSender存在且其中 BuildingSender存在。这样我的方法就知道哪个组被传递给各自的 Package类型。

我尝试使用 GroupBy 的逻辑是,我宁愿使查询尽可能通用,以便以后可以扩展到更多集和/或通过不必调用许多单独的查询来提高方法的性能,然后加入他们所有人。然而,似乎不可能在每个组上指定不同的选择查询。

@Hogan 的答案接近我想要做的事情。

霍根的回答

var result =
m.comm.SelectMany(x => x.person).Where(x => x.posts.Any()).Select(new () { x.name, x.posts})
.Union(m.comm.SelectMany(x=> x.building).Where(x => x.posts.Any()).Select(new () {x.name, x.posts}));

修改答案

这就是有效的:

return m.Communications.Where(x => x.SendingPerson.Any() && x.Posts.Any()).Select(u => 
new PostPackage(u.SendingPerson.First().Member,m,u.Posts.First()))
.Union(m.Communications.Where(x=> x.BuildingSender.Any() && x.Posts.Any()).Select(u => 
new PostPackage(u.BuildingSender.First().Building,m,u.Posts.First())));

不完全一样——昨天写这个问题时我的头有点雾。

最佳答案

我认为关键是 SelectMany 而不是 GroupBy ——这将“展平”子列表。正如我在下面所示的:

class Person{
  Collection<Communications> comm {get; set;}
}

class Communication{
  Collection<PersonSender> person {get; set;}
  Collection<BuildingSender> building {get; set;}
}

class PersonSender{
  string name {get; set; }
  Collection<Posts> posts {get; set;}
}

class BuildingSender{
  string name {get; set; }
  Collection<Posts> posts {get; set;}
}

假设 m 是一个人:

var result =
   m.comm.SelectMany(x => x.person).Where(x => x.posts.Any()).Select(new () { x.name, x.posts})
 .Union(m.comm.SelectMany(x=> x.building).Where(x => x.posts.Any()).Select(new () {x.name, x.posts}));

关于c# - LINQ Group By 如果一个对象有 x 个属性,则在每个组上进行选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18004387/

相关文章:

c# - 从单个数据表 c# 填充类的嵌套列表

c# - 在 LINQ select 中连接两个字段

c# - 如何在三个 IEnumerables 上使用 Zip

c# - 获取计数和名称

c# - 除了实例化 DAL 的 BLL 之外,还有什么选项允许在 n 层解决方案中进行单元测试,而无需将 DAL 暴露给 UI 或 BLL 暴露给 DAL?

c# - HttpSelfHostServer 和 HttpContext.Current

c# - 具有大量文件IO任务的多线程

linq - Entity Framework 、每种类型的表和 Linq - 获取 "Type"

c# - 如何在大型代码库中组织外部库

c# - protobuf-net 反序列化 : "Arithmetic operation resulted in an overflow."