2013-02-21 23 views
3

一直在尋找解決方案,但目前尚未找到解決方案。如何使用LINQ針對一個表返回父母和子女

我相當肯定它可能與一個linq調用但無法解決它。

我有以下數據結構

Id  ParentId  Name  ValidFlag 

1  NULL   parent 1 1 
2  NULL   parent 2 1 
3  NULL   parent 3 0 
4  1   child 1 1 
5  1   child 2 1 
6  2   child 3 1 
7  2   child 4 1 
8  3   child 5 1 
9  3   child 6 1 

現在我想要做的是所有有效的家長和他們的孩子所以這種情況下,我會回來的一切,除了ID = 3(父3)。

有沒有一種簡單的方法來做到這一點與LINQ?林猜測有但我的LinqIQ是非常有限的,我知道的基礎知識,但除此之外,我需要很多幫助。

這是ToLookup()還是Union的情況?

更新:

要,因爲我已經沒有這樣做,這兩種類型的記錄是在同一個表更具體,我想無論是其父母或子女返回1中的所有記錄查詢是否可能。

它不像只選擇ValidFlag = 1的所有記錄那麼簡單。源數據庫是一團糟,獲取所有記錄的唯一方法是找到「有效」父母,然後找到「有效」父母的所有孩子。我知道我可以做一個簡單的查詢來返回所有有效的父記錄,然後做一個單獨的查詢來查找這些父母的所有孩子,但結合成1 LINQ查詢是我失敗的地方,我希望這是可能的。在這種情況下,可能存在無效父母的有效子項,因此需要問題

+1

你能指定你想達到的最終結果嗎?孩子和家長會合併成一排,還是如何? – andri 2013-02-21 04:15:07

+0

ValidFlag是否影響您是否返回一行? – 2013-02-21 04:16:25

+0

請你可以顯示你已經嘗試過的代碼? – 2013-02-21 04:18:22

回答

2

這應該做的伎倆,(編輯:請參閱下面的不使用鮮明版)

(from parents in collection 
from all in collection 
where 
    parents.ValidFlag == 1 && 
    parents.ParentId == null && 
    all.ValidFlag == 1 && 
    (all.ParentId == null || all.ParentId == parents.Id) 
select all).Distinct(); 

上面的代碼應該有希望產生非常相似 的東西是什麼本身看起來像SQL ,也許除了 不同,這可能導致它返回更多的數據,實際上需要在客戶端上過濾 。的東西,如果有大量的數據,主要是如果有很多家長 的,因爲它會返回那些副本)

這裏是沒有明顯的呼叫修改了查詢,可能成爲一個 問題

from parents in collection // parents is only used to decide which children to get 
from all in collection // this is where we will actually grab our data from 
where 
    parents.ValidFlag == 1 && // only include parents that are valid 
    parents.ParentId == null && // and that are parents 
    all.ValidFlag == 1 && // only include entries that are valid 
    (
     (all.ParentId == null && all.Id == parents.Id) || // If entry is a parent, match with itself to limit returns to 1 
     all.ParentId == parents.Id // otherwise, parentid should match one of the valid parents. 
    ) 
select all 
+0

感謝大家提供的幫助,我很感激。我最終在這裏使用了第二個示例,它完美地工作。 – Mark 2013-02-21 06:28:54

+0

我可能會遲到...但我需要幫助才能做出這個遞歸,如果孩子也可以有一個孩子,我不能將我的頭包裹在它周圍。 – 2017-11-27 13:44:24

1

這應該這樣做。創建一個包含該數據結構的對象類型的通用列表。然後使用.Where擴展名返回相同類型的IEnumerable。

List<YourObject> list = new List<YourObject>(); 
    IEnumerable<YourbObject> validItems = list.Where(x=>x.ValidFlag=1); 
+0

謝謝丹尼,對不起,它不是這個簡單的不幸,孩子只能選擇一旦父母是知道,我會修改我的問題,即。不是每個孩子的記錄都會那麼簡單,我上面的數據的例子不是很好,我的歉意 – Mark 2013-02-21 04:17:00

0

考慮以下LINQ到SQL實體:

enter image description here

假設我們命名爲喜歡ChildTablesParentTablesOneToMany關係的兩側,然後將下面的代碼應該做的工作

//create data context 
MyTableDataContext dc = new MyTableDataContext("Your connection string"); 
//find all children, i.e. the entities with ParentId set 
var allChildEntities = dc.MyTable.Where(t=>t.ParentId.HasValue); 
//find all valid parents, which have no parent and no children 
var allParentsWithChild = dc.MyTable.Where(c => !c.ParentId.HasValue && 
               !c.ChildTables.Any()); 
//union the results 
var result = allChildEntities.Union(allParentsWithChild); 

如果在Id a之間存在外鍵關係nd ParentId,那就夠了。如果不是,你也應該搜索孩子的實體,而不是現有的父母。但是,這可能會更容易完成與純sql

0

我打算使用GroupJoin,但這應該滿足您的要求。

var query = dataContext.YourTable.Where(x => x.ValidFlag == 1 && 
(x.ParentId == null || 
    dataContext.YourTable.Where(y => y.ParentId == x.Id) 
    .First().ValidFlag == 1)) 
.ToList(); 
         . 
0

您的樣本數據,這將工作:

 var validData = from d in data 
         where (!d.ParentID.HasValue && d.IsValid) //select all valid parents 
         || (d.ParentID.HasValue && data.Where(p => !p.ParentID.HasValue && p.IsValid).Select(p => p.ID).Contains(d.ParentID.Value)) //select children 
         select d; 

但如果在你的數據是多層次結構將無法正常工作,並且要選擇子兒太。

另一件事,我不確定上述是否可以在linq-to-sql或其他linq提供程序上工作,但它對內存數據有效。

0

如果您正在使用實體框架並具有導航屬性,您可以執行以下操作。從這個問題來看,這是不是很清楚。

var query = db.YourTable 
    .Where(x => x.Parent != null && x.Parent.ValidFlag == 1) 
    .GroupBy(x => x.ParentId) 
    .Select(g => new { ParentId = g.Key, Children = g.ToList() }) 
    .ToList(); 
0

這個 「錯誤」 的辦法解決思想,你想要的SQL是:

SELECT * FROM MyTable 
WHERE IsValid = 1 AND 
(ParentID IS NULL -- Parents 
OR ParentID IN (SELECT ID FROM MyTable WHERE IsValid = 1 AND ParentID IS NULL)) 
    -- Children 

讓您隨心所欲的LINQ是:

var result = from d in MyTable 
      where d.ValidFlag == 1 
       && (d.ParentId == null 
       || (from p in MyTable where p.ValidFlag == 1 && p.ParentId == null 
        && p.Id == d.ParentId select p.Id).Any()) 
      select d; 

(不太相同的SQL ,但實際上是這樣。)