2016-01-15 56 views
0

我們有一條規則,不在服務層之外暴露IQueryable<T>IEnumerable<T>,所以下游代碼無法修改前往數據庫的查詢。這意味着我們返回的類型就像IList或ICollection。在沒有返回IQueryable或IEnumerable的情況下返回單實體框架查詢中的父項和子項?

我想知道如何編寫linq查詢來獲取父項,並且它是孩子在單次訪問數據庫時沒有將子集合定義爲IQueryableIEnumerable

例如,假設從服務返回的類型ICollection<Parent>其中Parent的定義是這樣的:

public class Parent 
{ 
    public int ParentId { get; set; } 
    public string ParentName { get; set; } 
    public ICollection<Child> Children { get; set; } 
} 

如果我定義查詢,因爲這...

from p in dbContext.Parents 
where p.Name.Contains("test") 
select new Parent 
{ 
    Children =from c in dbContext.Children 
    where c.ParentId == p.ParentId 
    select c; 
} 

一點也沒有因爲IQueryable沒有實現ICollection。如果我將.ToList()添加到父級和子級集合中,它會進行編譯,但現在它將爲每個父級單獨訪問數據庫以獲取它的子級。

當我寫這個問題時,我想到,也許答案是編寫Linq查詢來選擇匿名類型,然後將其映射到實際返回的類型。我們使用AutoMapper,它可以幫助映射。任何理由爲什麼這不起作用?在映射對象之前,我必須調用.ToList()以確保映射時不會遇到同樣的問題嗎?

+0

[Entity Framework遞歸地包含了來自包含集合中的每個實體的集合]的可能重複(http://stackoverflow.com/questions/24945115/entity-framework-recursively-include-collection-for-each-entity-from-包括公司) –

+2

我可以理解,不想暴露'IQueryable',但我沒有看到不暴露'IEnumerable'的邏輯。首先,您的替代方案都會實施它。 –

+1

另外,你的例子不能編譯(集合沒有名字,你的選擇器沒有指定任何屬性)。它看起來像你的要求可以滿足我只是返回'dbContext.Parents.Include(x => x.Children).Where(x => x.Name.Contains(「test」))',所以它可能不會真正說明你的觀點。 –

回答

2

如果你有一個像這樣在你的Parent實體導航屬性:

public class Parent 
{ 
    public int ParentId { get; set; } 
    public string ParentName { get; set; } 
    public virtual ICollection<Child> Children { get; set; } 
    //.. 
} 

那我建議你在你的服務層創建兩個新的類(可能是ParentViewModel,並ChildViewModel)保存的結果你查詢。在這兩個類中只聲明表示層中需要的屬性。然後使用Automapper將您的實體與您的ViewModel類映射。

在此之後,你可以做這樣的查詢:

var query =dbContext.Parents 
        .Include(p=>p.Children) // load the related entities as part of the query 
        .Where(p=>p.ParentName.Contains("test")) 
        .ProjectTo<ParentViewModel>(); 

使用ProjectTo Automapper的擴展方法。

正如你可以在link我上面引述看到,Automapper支持嵌套映射,因此,如果你在你的ParentViewModelICollection<ChildViewModel>類型的屬性,你也映射Child實體,其視圖模型,然後Automapper將會將自動嘗試映射從一種類型到另一種類型。

所有這些將在您的數據庫的一次往返中發生,因爲ProjectToIQueryable<TEntity>擴展方法,它被翻譯爲Select

+0

拜託,請你解釋爲什麼要改進我的答案? – octavioccl

+0

也許,*也許*因爲'ProjectTo'返回OP不需要的'IQueryable'。但我認爲這是挑剔的。 –

相關問題