2013-02-21 1 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 

내가하고 싶은 것은이 경우 내가 아이디 = 3 (부모 3)를 제외한 모든 반환 모든 유효한 부모와 자녀를 돌려 주어에게 있습니다.

LINQ를 사용하여이 작업을 수행하는 간단한 방법이 있습니까? 내 추측하지만 거기에 내 LinqIQ 매우 제한된, 나는 기초를 알고 있지만 그 이상의 도움이 많이 필요합니다.

ToLookup() 또는 Union의 경우입니까?

업데이트 : 내가 1 년에 부모 나 자녀 여부 모든 레코드를 반환 할

내가 그렇게하는 데 실패했습니다 기록의 두 가지 유형은 같은 테이블에있는 것처럼 구체적으로는 가능한 경우 쿼리.

ValidFlag = 1 인 모든 레코드를 선택하는 것만 큼 간단하지가 않습니다. 원본 데이터베이스가 엉망이며 모든 레코드를 가져 오는 유일한 방법은 "유효한"부모를 찾은 다음 "유효한"부모의 모든 자식을 찾는 것입니다 . 나는 모든 유효한 부모 레코드를 반환하는 간단한 쿼리를 수행 한 다음 해당 부모의 모든 자식을 찾기 위해 별도의 쿼리를 수행 할 수 있지만 1 LINQ 쿼리로 결합하면 실패 할 수 있음을 알고 있습니다. 이 경우 유효하지 않은 부모 항목의 유효한 하위 항목이있을 수 있으므로 질문이 필요합니다.

+1

달성하고자하는 최종 결과를 지정할 수 있습니까? 자식과 부모가 한 행에 합쳐 지거나 어떻게 될까요? – andri

+0

ValidFlag는 행을 반환하는지 여부에 영향을주는 유일한 것입니까? –

+0

시도한 코드를 보여줄 수 있습니까? –

답변

2

이 트릭을 수행한다 (고유 사용하지 않는 버전은 아래를 참조 편집.) 어쩌면 별개 기호를 제외하면 더 많은 데이터를 반환 할 수 있습니다. 실제로는 클라이언트에서 필터링해야 할 데이터가 입니다. 그것은 사람들의 중복) 여기

는 별개의 호출없이 수정 된 쿼리입니다 반환하기 때문에 부모 의 많은이 있다면 주로, 많은 데이터가있을 경우 문제가 될 수있는 뭔가

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

+0

나는 늦을지도 모른다. 그러나이 재귀 적으로 만드는 데 도움이 필요하다. 아이도 아이를 가질 수 있다면, 나는 그 주위에 머리를 감쌀 수 없다. –

1

이렇게해야합니다. 해당 데이터 구조가 포함 된 개체 유형의 일반 목록을 만듭니다. 그런 다음 동일한 유형의 IEnumerable을 반환하는 .Where 확장명을 사용합니다.

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

감사합니다. Danny, 죄송합니다. 불행히도이 간단한 유감스럽게도 부모님은 아이들을 선택할 수 있습니다. 알다시피, 나는 내 질문을 수정할 것이다. 모든 어린이 기록이 그다지 간단하지 않을 것입니다. 위의 데이터 예는 매우 좋지 않았습니다. – Mark

0

은 다음과 Linq는 SQL로 법인 고려 : 우리가 ChildTablesParentTables 같은 OneToMany 관계의 측면을 명명 한

enter image description here

한다고 가정을, 다음 코드는 일을해야

//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 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; 

하지만 데이터의 다단계 계층 구조가있는 경우 작동하지 않습니다, 당신은 너무 하위 아이들을 선택합니다 : 샘플 데이터에 대한

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

이 작동합니다 .

다른 건, 위의 linq-to-SQL 또는 다른 linq 공급자에서 작동하는지 확실하지 않지만 메모리 데이터를 작동합니다. 그 자체가 SQL에서 어떻게 생겼는지

(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(); 

희망 매우 유사 무언가를 생성해야 위의 코드를 :

0

하는 경우 Entity Framework를 사용하고 탐색 속성이 있으면 다음 작업을 수행 할 수 있습니다. 이것이 사실인지 여부는 의문의 여지가 없습니다. 은 "잘못"방법의 주위에 이것에 대해 생각

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 , 효과적입니다.)

관련 문제