복붙노트

[SQL] Linq는 계층 적 데이터 - 옵션 및 성능

SQL

Linq는 계층 적 데이터 - 옵션 및 성능

좀 계층 적 데이터가 - 각 항목은 ID와 (널 (NULL)) 상위 항목 ID가 있습니다. 나는 주어진 항목 아래에 트리에있는 모든 항목을 검색합니다. 이것은 SQL 서버 2005 데이터베이스입니다. 나는 C # 3.5에서 SQL에 LINQ로 질의하고있다.

SQL에 LINQ를 직접 공통 테이블 식을 지원하지 않습니다. 내 선택은 여러 가지 LINQ 쿼리를 사용하여 코드의 데이터를 조립, 또는 CTE를 표면 데이터베이스에보기를 만들 수 있습니다.

어떤 옵션 (또는 다른 옵션) 당신이 데이터 볼륨이 커질 때 더 잘 수행 할 생각하십니까? SQL 서버 2008의 인 HierachyId 유형은 SQL Linq에 지원됩니까?

해결법

  1. ==============================

    1.나는보기와 CTE에 따라 관련 테이블 기반 기능을 설정합니다. 응용 프로그램 측의 논리를 구현할 수있는 동안이에 대한 나의 추론, 즉이다,이 응용 프로그램의 계산을 위해 와이어를 통해 중간 데이터 전송을 포함한다. DBML 디자이너를 사용하여보기는 표 엔티티로 변환합니다. 그런 다음 표 엔티티와 연관 기능 및 도면에 의해 정의 된 형태의 파생 객체에 DataContext를 생성하는 방법을 호출 할 수있다. 결과 세트를 구성하기보다는 사후 뷰에 의해 정의 된 결과 집합에 조건을 적용하는 동안 쿼리 엔진을 테이블 기반 기능을 허용 사용하면 계정으로 매개 변수를 사용합니다.

    나는보기와 CTE에 따라 관련 테이블 기반 기능을 설정합니다. 응용 프로그램 측의 논리를 구현할 수있는 동안이에 대한 나의 추론, 즉이다,이 응용 프로그램의 계산을 위해 와이어를 통해 중간 데이터 전송을 포함한다. DBML 디자이너를 사용하여보기는 표 엔티티로 변환합니다. 그런 다음 표 엔티티와 연관 기능 및 도면에 의해 정의 된 형태의 파생 객체에 DataContext를 생성하는 방법을 호출 할 수있다. 결과 세트를 구성하기보다는 사후 뷰에 의해 정의 된 결과 집합에 조건을 적용하는 동안 쿼리 엔진을 테이블 기반 기능을 허용 사용하면 계정으로 매개 변수를 사용합니다.

    CREATE TABLE [dbo].[hierarchical_table](
        [id] [int] IDENTITY(1,1) NOT NULL,
        [parent_id] [int] NULL,
        [data] [varchar](255) NOT NULL,
     CONSTRAINT [PK_hierarchical_table] PRIMARY KEY CLUSTERED 
    (
        [id] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    CREATE VIEW [dbo].[vw_recursive_view]
    AS
    WITH hierarchy_cte(id, parent_id, data, lvl) AS
    (SELECT     id, parent_id, data, 0 AS lvl
          FROM         dbo.hierarchical_table
          WHERE     (parent_id IS NULL)
          UNION ALL
          SELECT     t1.id, t1.parent_id, t1.data, h.lvl + 1 AS lvl
          FROM         dbo.hierarchical_table AS t1 INNER JOIN
                                hierarchy_cte AS h ON t1.parent_id = h.id)
    SELECT     id, parent_id, data, lvl
    FROM         hierarchy_cte AS result
    
    
    CREATE FUNCTION [dbo].[fn_tree_for_parent] 
    (
        @parent int
    )
    RETURNS 
    @result TABLE 
    (
        id int not null,
        parent_id int,
        data varchar(255) not null,
        lvl int not null
    )
    AS
    BEGIN
        WITH hierarchy_cte(id, parent_id, data, lvl) AS
       (SELECT     id, parent_id, data, 0 AS lvl
            FROM         dbo.hierarchical_table
            WHERE     (id = @parent OR (parent_id IS NULL AND @parent IS NULL))
            UNION ALL
            SELECT     t1.id, t1.parent_id, t1.data, h.lvl + 1 AS lvl
            FROM         dbo.hierarchical_table AS t1 INNER JOIN
                hierarchy_cte AS h ON t1.parent_id = h.id)
        INSERT INTO @result
        SELECT     id, parent_id, data, lvl
        FROM         hierarchy_cte AS result
    RETURN 
    END
    
    ALTER TABLE [dbo].[hierarchical_table]  WITH CHECK ADD  CONSTRAINT [FK_hierarchical_table_hierarchical_table] FOREIGN KEY([parent_id])
    REFERENCES [dbo].[hierarchical_table] ([id])
    
    ALTER TABLE [dbo].[hierarchical_table] CHECK CONSTRAINT [FK_hierarchical_table_hierarchical_table]
    

    : 몇 가지 합리적인 명명 체계를 가정 -처럼 사용하려면 뭔가를 할 것입니다

    using (DataContext dc = new HierarchicalDataContext())
    {
        HierarchicalTableEntity h = (from e in dc.HierarchicalTableEntities
                                     select e).First();
        var query = dc.FnTreeForParent( h.ID );
        foreach (HierarchicalTableViewEntity entity in query) {
            ...process the tree node...
        }
    }
    
  2. ==============================

    2.이 옵션은 유용 할 수 있습니다

    이 옵션은 유용 할 수 있습니다

    LINQ AsHierarchy () 확장 방법 http://www.scip.be/index.php?Page=ArticlesNET18

  3. ==============================

    3.나는 놀랄 아무도 다른 데이터베이스 설계를 언급하지 않았다 있어요 - 계층의 요구가이 PARENT_ID 대신 계층 구조를 추적하는 다른 기업-2-엔티티 테이블을 사용하는 것이 좋습니다 여러 수준에서 평평하고 (그래서 저장 공간을 고려하지 않는다) 높은 성능을 검색 할 때 접근하다.

    나는 놀랄 아무도 다른 데이터베이스 설계를 언급하지 않았다 있어요 - 계층의 요구가이 PARENT_ID 대신 계층 구조를 추적하는 다른 기업-2-엔티티 테이블을 사용하는 것이 좋습니다 여러 수준에서 평평하고 (그래서 저장 공간을 고려하지 않는다) 높은 성능을 검색 할 때 접근하다.

    그것은 하나의 부모 관계뿐만 아니라 여러 부모 관계, 레벨 표시와 관계의 다른 유형뿐만 아니라 수 있습니다 :

    CREATE TABLE Person (
      Id INTEGER,
      Name TEXT
    );
    
    CREATE TABLE PersonInPerson (
      PersonId INTEGER NOT NULL,
      InPersonId INTEGER NOT NULL,
      Level INTEGER,
      RelationKind VARCHAR(1)
    );
    
  4. ==============================

    4.나는이 두 가지 일을했다 :

    나는이 두 가지 일을했다 :

  5. ==============================

    5.이 확장 방법은 잠재적으로 된 IQueryable를 사용하도록 수정 될 수 있습니다. 나는 개체의 컬렉션에 과거에 성공적으로 사용했습니다. 그것은 당신의 시나리오에 대해 작동 할 수 있습니다.

    이 확장 방법은 잠재적으로 된 IQueryable를 사용하도록 수정 될 수 있습니다. 나는 개체의 컬렉션에 과거에 성공적으로 사용했습니다. 그것은 당신의 시나리오에 대해 작동 할 수 있습니다.

    public static IEnumerable<T> ByHierarchy<T>(
     this IEnumerable<T> source, Func<T, bool> startWith, Func<T, T, bool> connectBy)
    {
      if (source == null)
       throw new ArgumentNullException("source");
    
      if (startWith == null)
       throw new ArgumentNullException("startWith");
    
      if (connectBy == null)
       throw new ArgumentNullException("connectBy");
    
      foreach (T root in source.Where(startWith))
      {
       yield return root;
       foreach (T child in source.ByHierarchy(c => connectBy(root, c), connectBy))
       {
        yield return child;
       }
     }
    }
    

    내가 전화하는 방법을 여기에 있습니다 :

    comments.ByHierarchy(comment => comment.ParentNum == parentNum, 
     (parent, child) => child.ParentNum == parent.CommentNum && includeChildren)
    

    이 코드는 여기에있는 코드의 개선, 버그 수정 버전입니다.

  6. ==============================

    6.MS SQL 2008에서는 SQL2005에서 당신은 수동으로 구현해야 할 수도 있습니다, 직접 HIERARCHYID를 사용할 수 있습니다. ParentID 대형 데이터 세트에 그 성능이 좋은하지 않습니다. 또한 주제에 대한 자세한 설명은이 문서를 확인하십시오.

    MS SQL 2008에서는 SQL2005에서 당신은 수동으로 구현해야 할 수도 있습니다, 직접 HIERARCHYID를 사용할 수 있습니다. ParentID 대형 데이터 세트에 그 성능이 좋은하지 않습니다. 또한 주제에 대한 자세한 설명은이 문서를 확인하십시오.

  7. ==============================

    7.내가 롭 Conery의 블로그 (백금 주변에 체크. (6)이 코드도 코드 플렉스에)에서이 방법을 가지고 나는 그것을 사용하여 사랑 해요. 이것은 다수의 "하위"수준을 지원하기 위해 refashioned 수 있습니다.

    내가 롭 Conery의 블로그 (백금 주변에 체크. (6)이 코드도 코드 플렉스에)에서이 방법을 가지고 나는 그것을 사용하여 사랑 해요. 이것은 다수의 "하위"수준을 지원하기 위해 refashioned 수 있습니다.

    var categories = from c in db.Categories
                     select new Category
                     {
                         CategoryID = c.CategoryID,
                         ParentCategoryID = c.ParentCategoryID,
                         SubCategories = new List<Category>(
                                          from sc in db.Categories
                                          where sc.ParentCategoryID == c.CategoryID
                                          select new Category {
                                            CategoryID = sc.CategoryID, 
                                            ParentProductID = sc.ParentProductID
                                            }
                                          )
                                 };
    
  8. ==============================

    8.클라이언트 측에서 데이터를 가져 오는에 문제는 당신이 당신이 갈 필요가 얼마나 깊은 결코 할 수 있다는 것입니다. 이 방법은 깊이 당 하나의 왕복을 할 것입니다 그리고 하나 명의 왕복에 지정된 깊이 0에서 할 union'd 수 있습니다.

    클라이언트 측에서 데이터를 가져 오는에 문제는 당신이 당신이 갈 필요가 얼마나 깊은 결코 할 수 있다는 것입니다. 이 방법은 깊이 당 하나의 왕복을 할 것입니다 그리고 하나 명의 왕복에 지정된 깊이 0에서 할 union'd 수 있습니다.

    public IQueryable<Node> GetChildrenAtDepth(int NodeID, int depth)
    {
      IQueryable<Node> query = db.Nodes.Where(n => n.NodeID == NodeID);
      for(int i = 0; i < depth; i++)
        query = query.SelectMany(n => n.Children);
           //use this if the Children association has not been defined
        //query = query.SelectMany(n => db.Nodes.Where(c => c.ParentID == n.NodeID));
      return query;
    }
    

    그것은, 그러나, 임의의 깊이를 할 수 없습니다. 당신이 정말로 임의의 깊이를 요구하는 경우, 데이터베이스에서 그렇게 할 필요가 - 당신은 정지에 대한 올바른 결정을 내릴 수 있습니다.

  9. ==============================

    9.다음 링크를 참조하시기 바랍니다.

    다음 링크를 참조하시기 바랍니다.

    http://support.microsoft.com/default.aspx?scid=kb;en-us;q248915

  10. from https://stackoverflow.com/questions/202912/hierarchical-data-in-linq-options-and-performance by cc-by-sa and MIT license