2012-05-20 3 views
1

나는 ParentId (Consumer를 가리킨다)과 Orgs 속성을 갖는 클래스 Org을 가지고 Org 인스턴스의 계층 구조를 가능하게한다. OrgId 속성을 가진 클래스 Customer도 있습니다. Owner이라는 Org 인스턴스가 있으면 해당 조직의 모든 Customer 인스턴스를 검색하려면 어떻게해야합니까? 즉, LINQ 전에 Org 트리의 '수동'통과를 루트로 Owner으로 수행합니다. 그래도 뭔가가 더 간단하다고 확신합니다.LINQ에서 계층 구조를 개체로 병합하려면 어떻게해야합니까?

예 : '영화', Id '1', 하위 조직이 ParentId가 '1'이고 하위 ID가 23 인 Idol이 'Horror'인 경우 모두를 쿼리하고 싶습니다. 영화 아래의 고객, 그래서 1과 23 모두의 OrgId를 가진 모든 고객을 얻어야합니다.

답변

1

Linq가 도움이되지 않지만 SQL Server는 도움이됩니다.

CREATE PROCEDURE [dbo].[OrganizationIds] 
    @rootId int 

AS 
    WITH OrgCte AS 
    ( 
     SELECT OrganizationId FROM Organizations where OrganizationId = @rootId 
     UNION ALL 
     SELECT parent.OrganizationId FROM Organizations parent 
     INNER JOIN OrgCte child ON parent.Parent_OrganizationId = Child.OrganizationId 
    ) 
    SELECT * FROM OrgCte 

RETURN 0 

지금이 저장 프로 시저에 매핑 된 사용자의 컨텍스트에 함수 가져 오기를 추가

는 조직 IDS, 같은의 평평 목록을 생성하는 CTE를 만듭니다. 내가 생각

// get all org ids for specific root. This needs to be a separate 
// query or LtoE throws an exception regarding nullable int. 
var ids = OrganizationIds(2); 

// now find all customers 
Customers.Where (c => ids.Contains(c.Organization.OrganizationId)).Dump(); 
0

불행히도, Entity Framework에는 기본적으로 없습니다. 자신 만의 솔루션을 구축해야합니다. 아마 당신은 루트까지 반복 할 필요가있을 것입니다. 당신은 (여기 : 3)이 방법으로 부모의 정적으로 고정 된 수의 제한됩니다

... 
select new { x.Customer, x.Parent.Customer, x.Parent.Parent.Customer } 

:하지만 것이 같이 이동 한 부모의 특정 번호를 얻기 위해 EF를 요청하여이 알고리즘을 최적화 할 수 있습니다 데이터베이스 왕복 2/3을 절약 할 수 있습니다.

편집 : 데이터 모델을 제대로 이해하지 못했지만 생각이 분명하기를 바랍니다. 나는이 같은 접근 방식을 적응 의견과 편집에 대응 :

편집 2

var rootOrg = ...; 
var orgLevels = new [] { 
select o from db.Orgs where o == rootOrg, //level 0 
select o from db.Orgs where o.ParentOrg == rootOrg, //level 1 
select o from db.Orgs where o.ParentOrg.ParentOrg == rootOrg, //level 2 
select o from db.Orgs where o.ParentOrg.ParentOrg.ParentOrg == rootOrg, //level 3 
}; 
var setOfAllOrgsInSubtree = orgLevels.Aggregate((a, b) => a.Union(b)); //query for all org levels 

var customers = from c in db.Customers where setOfAllOrgsInSubtree.Contains(c.Org) select c; 

공지 사항이 한정된 최대 트리 깊이에 대한이 유일한 작품. 실제로 이것은 보통 (10 또는 20) 경우입니다.

성능은 좋지 않지만 LINQ-to-Entities 전용 솔루션입니다.

+0

:

public partial class TestEntities : ObjectContext { public ObjectResult<int?> OrganizationIds(int? rootId) { ... 

지금이 같은 쿼리를 사용할 수 있습니다 : 이것은 당신의 컨텍스트 (반환 값은 원래 Parent_OrganizationId가 INT NULL로 선언되어 있기 때문에 널 (NULL) INT 있습니다)에 방법 결과 너는 내 요점을 놓쳤다. 내 예제 모델에서 하나의 객체의 이름을 변경하여 명확하게합니다. 한 조직이 나무 조직의 근원 인 경우 그 조직의 이드와 나무 아래에있는 모든 조직의 이드를 가져와야합니다. – ProfK

+0

일부 코드를 추가했습니다. – usr

관련 문제