2010-04-01 2 views
3

두 개의 열, GroupId 및 ParentId (모두 GUIDS) 테이블이 있습니다. 테이블은 계층 구조를 형성하므로 "GroupId"필드의 값을 찾을 수 있습니다.이 필드에서 해당 부모 항목을 볼 수 있습니다. 이 ParentId는 다른 레코드의 GroupId에도 나타납니다. 이 방법을 사용하여 임의의 지점에서 루트 (루트는 빈 GUID 임)로 계층 트리를 걸어 갈 수 있습니다. GroupId를 알면 레코드 목록을 얻고 싶습니다. GroupId와 모든 부모가 루트 레코드로 돌아가는 기록입니다. Linq에서 가능합니까? 그렇다면 코드 스 니펫을 제공 할 수 있습니까?Linq를 사용하여 계층 구조 테이블을 걷기

답변

5

LINQ는 재귀 선택을 처리하도록 설계되지 않았습니다.

LINQ to Objects에서이를 보완하기 위해 고유 한 확장 방법을 작성할 수도 있지만 LINQ to Entities는 SQL로 쉽게 변환되지 않는 기능을 선호하지 않습니다.

편집 : 충분히 재미있게, LINQ here 사용하여 재귀에 매트 워렌의 테이크에 대해 불평하지 않는 엔티티에 LINQ. 당신은 할 수 :

var result = db.Table.Where(item => item.GroupId == 5) 
        .Traverse(item => db.Table.Where(parent 
                 => item.ParentId == parent.GroupId)); 

여기에 정의 된 확장 메서드를 사용하여 :

static class LinqExtensions 
{ 
    public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, 
              Func<T,IEnumerable<T>> selector){ 
    foreach(T item in source){ 
     yield return item; 
     IEnumerable<T> children = selector(item); 
     foreach (T child in children.Traverse(selector)) 
     { 
      yield return child; 
     } 
    } 
} 

의 performace하지만, 가난 수 있습니다.

1

Linq에서는 분명히 가능하지만 계층 구조에서 각 레벨에 대해 DB 호출을해야합니다. 정확하게 최적은 아닙니다.

0

다른 응답자는 옳습니다. 여러 번의 왕복을해야하므로 성능이 크게 떨어질 것입니다. 이것은 당신의 특정한 경우에 따라 다소 달라질 것입니다. 그러나 당신의 나무는 깊어서 사람들이 자주이 작업을 수행하게 될 것입니다.

CTE를 사용하여이 작업을 수행하는 저장 프로 시저를 만들고 Entities Designer에서 와이어 링하여 잘 정의 된 엔터티를 반환하면 잘 처리 될 수 있습니다.

+0

이 작업을 수행하는 방법에 대한 정보를 얻을 수 있습니까? – Evildommer5