2

我有一些使用 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根据集合是否包含实例PersonSenderBuildingSender这些实例本身是否有实例来对集合进行分组Post

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

到目前为止,这就是我对实际查询的了解

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。此类中的每个方法都可以由我的应用程序中的控制器调用,请求一组Package对象。Package接受几种类型的对象IEntity作为参数,并将与对象具有的关系相关联的内容包装IEntity到一个界面中,任何其他在我的应用程序上显示信息的控制器都可以读取该界面。TLDRPackage是一个美化的适配器模式设计对象。

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

在我为这个问题编写的方法的情况下,用户m有一个Communication对象集合,其中每个对象Communication都来自一个指向用户的IEntity对象(或者PersonSender或) 。我的查询是试图将对象分成两组,一组包含所有存在的地方,一个包含存在的地方。这样我的方法就知道哪个组被传递给他们各自的类型。BuildingSendermCommunicationCommunicationPeronSenderBuildingSenderPackage

我尝试使用 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())));

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

4

1 回答 1

2

我认为关键是 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}));
于 2013-08-01T21:25:49.523 回答