LINQ Group加入IGrouping

时间:2015-11-10 11:43:32

标签: c# entity-framework linq

想象一下,我的EF DataContext中有两个实体:

class Person
{
  int Id { get; set; }
  ...
}

class Address
{
  int PersonId { get; set; }
  string EMail { get; set; }
  ...
}

没有导航属性(我不想介绍任何导航属性)所以我使用GroupJoin来获取一系列人们的地址。

所以我在做:

var result = context.Set<Person>()
                    .GroupJoin(context.Set<Address>(),
                      x => x.Id,
                      x => x.PersonId, (person, addresses) =>
                      new { Person = person, Addresses = addresses.DefaultIfEmpty() });

result目前的类型为IQueryable<'a>,其中'anew { Person, IEnumerable<Address> }

现在我无法弄清楚如何对其进行转换,以便我得到一个IEnumerable<IGrouping<Person, Address>>。根据我的理解,这基本上是同一种结构。

2 个答案:

答案 0 :(得分:2)

如果您只需要替换匿名类型以便能够定义函数结果,那么您可以使用自己的泛型类,例如

public class Grouping<TKey, TELement>
{
    public TKey Key { get; set; }
    public IEnumerable<TELement> Elements { get; set; }
}

var result = context.Set<Person>()
    .GroupJoin(context.Set<Address>(), x => x.Id, x => x.PersonId,
        (person, addresses) => new Grouping<Person, Address>
        {
            Key = person,
            Elements = addresses.DefaultIfEmpty()
        });

结果的类型为IQueryable<Grouping<Person, Address>>,可用于进一步应用WhereOrderBy等。

重要提示:不要尝试在您的类型中实现IGrouping<TKey, TElement>(或一般IEnumerable<T> - EF不喜欢它并且会抛出运行时异常。也不要使用像Tuple.Create这样的构造函数或工厂助手。简单的属性获取/设置,没有其他(如在实体类中)。当然,无论你喜欢什么,你都可以给班级及其成员打电话。

答案 1 :(得分:1)

你可以做到的最好的方式可能是:

target\EShopper-1.0-SNAPSHOT\WEB-INF\classes\eshopper\web\configuration

然后:

springSecurityFilterChain

^注意,这并没有尝试使用EntityFramework。您可能需要保留匿名对象,请致电public class Grouping<TKey, TElement> : IGrouping<TKey, TElement> { private IEnumerable<TElement> collection; public Grouping(TKey key, IEnumerable<TElement> collection) { Key = key; this.collection = collection; } public TKey Key { get; set; } public IEnumerator<TElement> GetEnumerator() { return collection.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } ,然后选择新的var result = context.Set<Person>() .GroupJoin(context.Set<Address>(), x => x.Id, x => x.PersonId, (person, addresses) => new Grouping<Person, Address>(person, addresses.DefaultIfEmpty() }); //Return type can be defined as IEnumerable<IGrouping<Person, Address>> 类型。

或者,您可以使用ToList代替Grouping。这将为每个地址提供一行(即使它是同一个人),然后您可以使用Join的@schglurps建议

所以:

GroupJoin

然而,如果某人没有地址,它将不会出现在结果集合中。如果这很好,这个解决方案就更简洁了。