2011-03-14 26 views
2

再次感謝您發佈的所有精彩答案!如何從SQL中讀取父數據和子數據?

我在SQL中有兩個表。第一個定義了父項,並且有一個名爲ParentId的主鍵列。我也有一個子表,它有一個主鍵,一個外鍵爲'ParentId'。所以這兩張表格構成了一對單親 - 對許多孩子的關係。

問題是拉出父+子數據C#代碼的最有效方法是什麼?該數據讀入以下對象:

public class Parent 
{ 
    public int ParentId { get; set; } 
    public List<Child> Children { get; set; } 
    // ... many more properties ... // 
} 


public class Child 
{ 
    public int ChildId { get; set; } 
    public string Description { get; set; } 
    // ... many more properties ... // 
} 

如果我使用下面的查詢我會得到家長和孩子們一次,每個家長都會被重複多次,許多孩子有:

SELECT 
    p.ParentId as 'ParentId', 
    c.ChildId as 'ChildId', 
    -- other relevant fields -- 
FROM 
    Parents p 
INNER JOIN 
    Children c 
ON 
    p.ParentId = c.ParentId 

使用這種方法,我必須找到所有獨特的父行,然後讀取所有的孩子。好處是我只能做1次到db。

這樣做的第二個版本是分別讀取所有家長:

SELECT * FROM Parents 

,然後分別讀取所有的孩子:

SELECT * FROM Children 

,並使用LINQ帶孩子合併所有的父母。這種方法使2次訪問數據庫。

第三個也是最後一個(也是效率最低的)方法是抓住所有的父母,並在構造每個父對象時,前往數據庫以獲取其所有孩子。這種方法需要n + 1個連接:對於所有父母來說都是1,對於每個父母來說,有n次到所有孩子的旅行。

任何建議如何做到這一點更容易?當然,我不能擺脫使用存儲過程,我不能使用LINQ2SQL或EF。你更喜歡數據表還是數據讀取器?如果是的話,如何使用方法1或2?

感謝, 馬丁

回答

2

我喜歡拉在一個查詢所有的結果,只是建立樹在一個循環

SELECT p.ParentId as 'ParentId', null as 'ChildId' 
    FROM Parents p 
    UNION ALL 
    SELECT c.ParentId as 'ParentId', c.ChildId as 'ChildId' 
    FROM Children c 

    List<Parent> result = new List<Parent>(); 
    Parent current; 
    while (dr.Read()) 
    { 
     if (string.isNullOrEmpty(dr['ChildId'])) 
     { 
     //create and initialize your parent object here and set to current 
     } 
     else if (!string.isNullOrEmpty(dr['ChildId']) 
       && dr['ParentId'].ToString().Equals(current.ParentId.ToString()) 
     { 
     //create and initialize child 
     //add child to parents child collection 
     } 
    } 
0

我一般都在表級別這一決定。有些桌子我經常需要孩子,所以我馬上抓住他們。在其他情況下訪問孩子是一個罕見的,所以我懶加載他們。

+0

我顯然需要孩子這就是爲什麼我問的問題放在首位。 – bleepzter 2011-03-14 21:03:00

0

我猜想選項#2會比選項1更有效的帶寬(因爲您不重複任何數據)。

您可以在單個存儲過程中同時執行兩個查詢,並通過使用sqldataadapter(即(new SqlDataAdapter(command)).Fill(myDataSet),其中myDataSet將包含這兩個表)的代碼執行該過程。

從那裏,你會讀出第一個表,創建由的ParentId父母的字典(在Dictionary<int, Parent>),然後只需在第二表中讀取每一行補充孩子:

parents[(int)myDataSet.Tables[1]["ParentId"]].Children.Add(new Child() { etc }); 

的僞代碼可能關閉了一點,但希望你得到的總體思路

1

使用這種方法,我必須找到 所有獨特父行,然後 讀取所有的孩子們。

您可以只包含一個order by p.ParentId。這確保來自同一父母的所有孩子都在連續的行中。所以你可以閱讀下一行,如果父母已經改變,創建一個新的父對象,否則將孩子添加到前一個父母。無需搜索唯一的父行。