簡體   English   中英

LINQ Group加入IGrouping

[英]LINQ GroupJoin to IGrouping

想象一下,我的EF DataContext中有兩個實體:

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

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

沒有導航屬性(並且我不想介紹任何屬性),因此我使用GroupJoin獲取具有其地址的一系列People。

所以我在做:

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>> 據我了解,這基本上是相同的結構。

如果您只需要替換匿名類型以便能夠定義函數結果,則可以為此使用自己的通用類。

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 簡單的屬性獲取/設置,別無其他(例如在實體類中)。 當然,您可以隨心所欲地調用該類及其成員。

可能最好的方法是:

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>>

^注意,這沒有在EntityFramework上嘗試過。 您可能需要保留匿名對象,調用ToList ,然后選擇新的Grouping類型。

或者,您可以使用Join代替GroupJoin 這將為您提供每個地址一行(即使是同一個人),然后您可以使用.GroupBy() @schglurps建議

所以:

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

但是 ,如果一個人沒有地址 ,它將不會出現在結果集中。 如果可以的話,此解決方案會更簡潔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM