2009-09-08 3 views
1

저는 ADO.NET Entity Framework에 어려움을 겪고 있습니다. 이것은 내 ER 다이어그램입니다.EF : 컨텍스트를 삭제 한 후 참조를로드합니까?

---------------------  -----------------  --------------- 
| GrandParentEntity |<-------| ParentEntity |<-------| ChildEntity | 
+-------------------+ 1 N +---------------+ 1 N +-------------+ 
| Id    |  | Id   |  | Id   | 
---------------------  | GrandParentFk |  | ParentFk | 
          -----------------  --------------- 

개체 컨텍스트의 수명에 대해 질문이 있습니까? 내가 다음과 같이 데이터를 요청한다고 가정 해 보겠습니다.

public static List<MyParentEntity> GetMyParentEntity() 
{ 
    using (var context = new MyObjectContext(blablabla...)) 
    { 
     var resultSet = from e in context.MyParentEntitySet select e; 
     return resultSet.ToList(); 
    } 
} 

나는 모든 상위 엔티티의 목록을받습니다. 나중에 (시간?) 사용자는 검사 할 항목을 결정합니다. (한편, 엔티티 객체는 응용 프로그램의 여러 계층을 통과.) 지금 레코드의 모든 세부 사항을로드 할 수 있습니다이는 경우 ObjectDisposedException로 연결

public static void LoadChildren(MyParentEntity pEntity) 
{ 
    using (var context = new MyObjectContext(blablabla...)) 
    { 
     pEntity.GranParentEntityReference.Load(); 
     pEntity.ChildEntites.Load(); 
    } 
} 

을의 MyParentEntity 개체가에 연결이 끊어졌습니다 때문에 그것을 만든 객체 컨텍스트 이 문제를 처리 할 수있는 여러 가지 방법이 있습니다.

1) 항상 MyObjectContext 인스턴스 하나를 사용할 수 있으며 절대로 닫지 마십시오. 이것은 엄청난 메모리 낭비를 초래합니다.

2) "사용 (컨텍스트)"블록을 떠날 때마다 각 단일 개체 개체 (및 그 자식 및 부모 개체)를 수동으로 분리 할 수 ​​있습니다. 그리고 새로운 "using (context)"블록을 입력 할 때마다 첨부 할 수 있습니다. 많은 노력을합니다. (내 견해로 프레임 워크는 증가시키지 않고 노력을 줄여야합니다.) 새로운 "사용 (컨텍스트)"블록을 입력 할 때마다 다시로드하고 각 엔티티를 버리십시오. SQL Server에서 더 많은 (불필요한)로드로 이어지고 메모리를 낭비합니다.

4) 응용 프로그램이 시작될 때 모든 참조 정보와 모든 참조 정보 및 모든 참조 정보 및 해당 참조 정보를로드 할 수 있습니다. (토론이 정말 바보입니다!) ... (내가 옵션을 잊어 버리셨습니까

5)) 이제

당신을위한 큰 질문 : 내가 방법을 선택해야합니까? 내가 보지 못한 다른 방법이 있습니까? 아니면 프레임 워크의 정신을 완전히 오해 했습니까?

미리 감사드립니다.

업데이트 : Windows Forms 응용 프로그램입니다.

답변

2

두 번째 옵션을 사용합니다. 모든 단일 엔티티를 분리 할 필요가 없으므로 쿼리를 NoTracking으로 설정할 수 있으며 entite는 컨텍스트에 처음으로 연결되지 않으며 관계가 해제되지 않습니다 (로드 된 경우).

public static List<MyParentEntity> GetMyParentEntity(){ 
using (var context = new MyObjectContext(blablabla...)) 
{ 
    var resultSet = from e in context.MyParentEntitySet select e; 
    ((ObjectQuery)resultSet).MergeOption = MergeOption.NoTracking; 
    return resultSet.ToList(); 
}} 

두 번째 질문은 응용 프로그램이 웹 기반인지 또는 Windows 기반인지입니다. 웹 기반이라면 각 요청에 대해 컨텍스트가 생성되는 Singleton 패턴을 사용하는 것이 좋습니다.

public class Singleton 
{ 
    public static YourContext _context; 
    public static YourContext Context 
    { 
     get 
     { 
      //We are in a web app, use a request scope 
      if (HttpContext.Current != null) 
      { 
       YourContext current_context = (YourContext)HttpContext.Current.Items["_YourContext"]; 

       if (current_context == null) 
       { 
        current_context = new YourContext(); 
        HttpContext.Current.Items.Add("_YourContext", current_context);      
       } 
       return current_context; 
      } 
      else 
      { 
       if (_context == null) 
        _context = new YourContext(); 

       return _context; 
      } 
     } 
    } 
} 

는 정말 좋은 일이되지 않을 수도 정적 필드에 넣어, 그것은 웹 응용 프로그램이 아닌 경우 가장 좋은 방법입니다 무엇을 해야할지 모르겠어요. 이 프레임 워크는 약간 복잡하고 깊이있는 작동 방식을 읽으면 더 잘 이해하고 이러한 상황을 피할 수 있습니다. Julia Lerman의 Programming Entity Framework, 1st Edition을 사용했습니다.

+0

감사합니다. 질문은 Windows Forms 응용 프로그램에 대한 것입니다. 웹 서비스가 없습니다. 예, Julia Lermans의 책은 정말 훌륭합니다. 문제가 해결되어야한다는 힌트를 찾지 못했습니다. 귀하의 회신에 감사드립니다. – Chrigl

0

나는 옵션 5 건의 할 것입니다 :

public static MyParentEntity LoadChildren(MyParentEntity pEntity) 
{ 
     using (var context = new MyObjectContext(...)) 
     { 
      pEntity = (from e in context.MyParentEntitySet.Include("GranParentEntityReference").Include("ChildEntites") 
         where e.Id == pEntity.Id 
         select e).FirstOrDefault(); 
     return pEntity; 
     } 
} 

두 .Include

가 쿼리를 포함하고 있는지 확인하기 위해 여기 juste 있습니다를 (그리고 나는 그것을 오래지 않아 너무 발견하기 때문).

linqpad에서 테스트했는데 현재 작동하고 있지만 작동하지 않는 경우 (어쨌든이 문제에 결코 부딪치지 않았습니다.) 옵션 1이 나에게 더 나은 해결책 인 것 같습니다. 데이터의 양 또는 최종 사용자 단말기가 잠재적으로 낮은 specced인지를 결정합니다. (하나 더 아무것도없는 경우) 완전한 관계가없는 노트에

, 당신이 당신의 첫 번째 쿼리를 단순화 할 수 있습니다 :

using (var context = new MyObjectContext(blablabla...)) 
{ 
    var resultSet = context.MyParentEntitySet.ToList(); 
    return resultSet; 
} 

(하지만 문제가 해결되지 않습니다)

+0

. 당신이 제안하는 것은 나의 옵션 4와 비슷합니다 : 사용 여부와 관계없이 모든 데이터를 한번에로드하십시오. 우리는이 세 개의 간단한 테이블에 대해 이야기하는 것이 아니라 최대 500k 개의 레코드가있는 20 개 이상의 테이블에 대해 이야기하고 있습니다. 정말 "게으른로드"를 사용하고 싶습니다. – Chrigl

+0

흠, 내가 읽고 나서 아침 식사 직후에 이것을 타이핑했기 때문에 그렇다고해서 그것을 제외하고는 네 해결책 4와 같지 않다. 그것은 당신이 현재하고있는 실체에 대한 데이터를로드하고 있기 때문에 당신이해야 할 해결책과 더 비슷하다. 너가 원하는 시간이야. 예외를 발생시키지 않는 방식으로 .Load()를 다시 작성했습니다. :) –

0

그래서, Julia Lerman의 "Programming Entity Framework"에서 거의 하루 종일 읽은 후에 마침내 힌트를 발견했습니다. 20 장에서 "장기 실행 객체 컨텍스트 사용"에 대해 이야기합니다. 이것은 부분적으로 옵션 1과 3을 다룹니다. 사용자가 동일한보기를 유지하는 한 컨텍스트는 열려 있습니다. 컨텍스트는 UI가 새로운 뷰로 전환 할 때마다 삭제됩니다. 새보기에서 새 컨텍스트가 만들어지고 최근보기에서 다시 사용되는 모든 엔터티를 다시로드해야합니다.

나를 위해 많은 리팩토링을 의미하지만 내 부분은이 솔루션과 함께 살 수 있습니다 ...

관련 문제