2011-03-14 5 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 

이 방법을 사용하면 모든 고유 한 행을 찾아 모든 하위 항목을 읽어야합니다. 이점은 내가 DB에 1 번만 여행한다는 것이다.

SELECT * FROM Parents 

을 한 후 별도로 모든 어린이를 읽어 :

SELECT * FROM Children 

을하고 아이들과 모든 학부모 병합 LINQ를 사용

이의 두 번째 버전은 별도로 모든 부모를 읽는 것입니다. 이 방법은 db에 2 번 트립합니다.

세 번째이자 마지막 (또한 가장 비효율적 인) 방법은 모든 부모를 붙잡고 각 부모 개체를 구성하는 동안 모든 자식을 잡기 위해 DB로 이동하는 것입니다. 이 접근법은 n + 1 연결을 취합니다 : 모든 부모에 대해 1, 각 부모에 대해 모든 하위 항목을 가져 오는 n 개의 경로가 필요합니다.

이 작업을 쉽게 수행하는 방법에 대한 조언이 있으십니까? 내가 스토어드 프로 시저를 사용하지 못하게하고, LINQ2SQL 또는 EF를 사용할 수 없다고 허락했습니다. 데이터 테이블 대 DataReader를 선호합니까? 그렇다면 접근 방식 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

0

나는 # 2 옵션이 (당신이 어떤 데이터도 반복하지 않기 때문에) 옵션 # 1보다 현명한 대역폭이 될 것이라고 추측 할 것이다.

단일 저장 프로 시저에서 두 쿼리를 모두 가질 수 있으며 sqldataadapter (즉, (new SqlDataAdapter(command)).Fill(myDataSet), 여기서 myDataSet에 두 테이블이 포함됨)를 사용하여 코드를 통해 프로 시저를 실행할 수 있습니다.

거기에서 당신은 아이를 추가하기 위해 단순히 두 번째 테이블의 각 행을 읽어 ParentId에 의해 (A Dictionary<int, Parent>의) 부모의 사전을 만드는 첫 번째 테이블을 읽을 것 :

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

의사 코드는 아마 조금 떨어져 있지만 잘하면 당신은 고유 한 모든 부모 행을 찾기 위해 내가 가진 것이 방법을 사용하여 일반적인 생각

1

을 얻고, 모든 아이들을 읽어 .

order by p.ParentId을 포함 할 수 있습니다. 이렇게하면 같은 부모의 모든 자식이 연속 행에있게됩니다. 따라서 부모가 변경된 경우 다음 행을 읽고 새 부모 개체를 만들거나 이전 부모에 자식을 추가 할 수 있습니다. 고유 한 상위 행을 검색 할 필요가 없습니다.

관련 문제