2014-03-13 196 views
0

因此,這個問題很可笑,所以我們來看代碼。什麼是linq2entities相當於以下SQL的,因爲實體的樣子(表):Linq2Entities針對父母/子女關係的等效查詢,與所有父母和子女,篩選/訂購子女

Parent 
--- 
parent_id 
parent_field1 

Child 
-- 
child_id 
parent_id 
child_field1 
child_field2 

的SQL:

select p.*, c.* 
from parent p 
inner join p on 
    p.parent_id = child.parent_id 
where 
    c.child_field1 = some_appropriate_value 
order by 
    p.parent_field1 
    c.child_field2 

L2E讓我們這樣做條.include()和這似乎是適當的地方堅持孩子的排序和篩選,但include方法不接受一個表達式(爲什麼不呢?)。所以,我猜這是不能立即完成的,因爲這是很多文章的說法,但它們很老,我想知道EF6是否可能。

此外,我沒有訪問上下文,所以我需要lambda語法版本。

我要尋找一個結果對象的層次結構,看起來像:

Parent1 
    | 
    +-- ChildrenOfParent1 
    | 
Parent2 
    | 
    +-- ChildrenOfParent2 

等等。該列表最終將成爲IEnumerable。如果迭代了該列表,他們可以獲取該列表中每個父代的.Children屬性。

理想(我是在做夢這裏,我想),就是整體大小結果列表的可能是有限的。例如,如果有三個父母,每個有10個孩子,總共有33個(30個孩子+ 3個父母)實體,我可以將總列表限制爲某個任意值,例如13,在這種情況下,這會限制結果集與第一個父母及其所有孩子,第二個父母僅與其子女中的一個(共13個實體)。我猜所有這些都必須在代碼中手動完成,這是令人失望的,因爲它可以在SQL中輕鬆完成。

回答

0

當您從db使用entityframewrok獲取查詢來提取父母時,會在單個查詢中提取父代的字段。現在你有一個結果集是這樣的:

var parentsQuery = db.Parents.ToList(); 

那麼,如果你有對父foreign keyentityframework對父母產生了navigation property來訪問correspondingentity(例如Child表)。

在這種情況下

,當你使用這個navigation propertyparent entities這已經被取出,拿到childsentityframework創建到sql server每個父另一個連接。

例如如果parentsQuery計數15,通過下面的查詢entityframework創建15另一個連接,並得到15另一query

var Childs = parentsQuery.SelectMany(u => u.NavigationProperty_Childs).ToList(); 
在這些情況下,您可以使用 include防止額外的連接,以獲取所有 childs

與其parent,當你試圖讓父母在單個查詢中,像這樣:

var ParentIncludeChildsQuery = db.Parents.Include("Childs").ToList(); 

然後按照Queryentityframework不會創建任何連接,不會再得到任何查詢:

var Childs = ParentIncludeChildsQuery.SelectMany(u => u.NavigationProperty_Childs).ToList(); 

,但是,你不能創造任何條件和使用限制包括,您可以檢查任何約束或條件後,包括使用WhereJoinContains等等,像這樣:

var Childs = ParentIncludeChildsQuery.SelectMany(u => u.NavigationProperty_Childs 
    .Where(t => t.child_field1 = some_appropriate_value)).ToList(); 

但此查詢,所有的孩子都被提取從database是前

更好的方式來acheieve相當於SQL查詢:

 var query = parent.Join(child, 
       p => p.ID 
       c => c.ParentID 
       (p, c) => new { Parent = p, Child = c }) 
      .Where(u => u.Child.child_field1 == some_appropriate_value) 
      .OrderBy(u => u.Parent.parent_field1) 
      .ThenBy(u => u.Child.child_field2) 
      .ToList(); 
+0

如果我正確地讀這篇文章,這將創造兩個對象,父和子,並且該列表將只包含兩個項目。這不是我想要的。我希望所有的父母對象,與他們的子女財產與與父母關聯的孩子保持水分。 –

+0

這相當於你的'sql',並生成一個扁平列表,如果你想要分層結構,需要'groupby',檢查我的新帖子 –

0
根據您的評論

,這是你想要什麼:

var query = parent.Join(child, 
      p => p.ID, 
      c => c.ParentID, 
      (p, c) => new { Parent = p, Child = c }) 
     .Where(u => u.Child.child_field1 == some_appropriate_value) 
     .GroupBy(u => u.Parent) 
     .Select(u => new { 

      Parent = u.Key, 
      Childs = u.OrderBy(t => t.Child.child_field2).AsEnumerable() 
     }) 
     .OrderBy(u => u.Parent.parent_field1) 
     .ToList();