2012-07-12 1 views
1

SQL Server 데이터베이스의 데이터에 액세스하는 데 Entity Framework 4를 사용하는 ASP MVC 3 응용 프로그램이 있습니다.EF4 - 분리 개체의 관련 엔터티로드

나는 EF4를 사용하여 데이터베이스에서 엔티티를로드하는 시나리오가 있습니다. 그런 다음 정상적으로 관련 엔티티를로드 할 수 있습니다. 첫 번째로드 후에 엔티티를 캐시합니다. 이를 위해서는 직렬화가 필요합니다. 다음 요청에서 동일한 엔티티를로드하지만 이번에는 캐시에서로드합니다. 이로 인해 오브젝트가 컨텍스트에서 분리되지 않으므로 오브젝트가 컨텍스트에서 분리됩니다. 그런 다음 정상적으로 관련 엔티티를로드 할 수 없습니다.

이 이유는 개체가 컨텍스트에서 분리되어 추적되지 않는다는 것입니다. 문맥에 따라 객체를 추적 할 때, 실제 SQL 문을 실행하여 필요한 경우 변경 사항을 추적하고 적용 할 수 있다는 것을 알고 있습니다. 하지만 확실하지 않은 것은 첨부 된 상태가 관련 항목을로드하는 기능과 관련이 있는지 여부입니다.

여기에 몇 가지 사항이 있습니다. 이것은 모델 구조입니다. 이것은 간단하며 EF4가 작동하도록하기 위해 필요한 모든 것을 포함하지는 않습니다. 이것은 단순히 구조를 증명했습니다.

public class Segment 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public SegmentGroup Group { get; set; } 
} 
public class SegmentGroup 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public IEnumerable<Segment> Segments { get; set; } 
} 

그러면 DB 또는 캐시에서 세그먼트를 가져올 수 있습니다. 이 작업은 Manager 클래스에서 수행됩니다. 다시 한 번 매우 단순화되었습니다. 그래서 문제가 세그먼트가 DB에서로드 될 때 나는 세그먼트에 SegmentGroup에 액세스 할 수 있다는 것입니다

public ActionResult SegmentGroupName(Guid segmentId) 
{ 
    Segment segment = SegmentManager.GetSegment(segmentId); //Loaded from DB of Cache 
    return segment.Group.Name; //Group is accesable when segment is loaded from DB, but not from cache 
} 

:

public SegmentManager 
{ 
    public Segment GetSegment(Guid id) 
    { 
     string cacheKey = ... //generate specific cache key using Guid id 
     Segment segment = CacheProvider.Get<Segment>(cacheKey); 
     if(segment == null) //does not exist in cache yet - load from db and insert into cache 
     { 
      segment = repo.Find<Segment>(id); //roughly translates to: 
               //segment = dbcontext.Segments.SingleOrDefault(a => a.Id == id); 
      CacheProvider.Add(cacheKey, segment); 
     } 
     else //segment was found in cache - attach to context 
     { 
      repo.Attach<Segment>(segment); //dbcontext.Segments.Attach(segment); 
     } 
     return segment; 
    } 
} 

그래서이는 효율적으로이 같은이 세그먼트 관리자를 사용 나를 수 있습니다 캐시에서로드 될 때가 아닙니다.

그럼 내 세그먼트는 관련 엔터티에 액세스 할 수 있도록 캐시에서로드 된 후에 무엇을 할 수 있습니까? 모두 똑같은 패턴으로 모든 모델 관리자에게 적용 할 수있는 일반적인 솔루션이 필요합니다. 나는 캐싱하지 않는 것보다 실제로 비싸기 때문에 모든 관련 엔티티를로드하거나 수동으로로드하는 것을 피하려고합니다. 나는 물건들이 캐싱하기 전에 어디로 되돌아 가기를 원한다. :)

코드 데모는 매우 단순 해 지므로 일부 현실적인 가정을해야합니다.

답변

0

나는 Schrodinger 's Code로 언급 한 것과 비슷한 소리를 들었습니다 ... 내 모델을 내보기로 넘어가는 비슷한 문제가 생겼지 만 관련된 엔티티에 액세스하려고 할 때 오류가 발생했습니다. 닫히고있는 오브젝트 컨텍스트로 이동합니다. 주체를 내보기로 전달하기 전에 관련 개체를 관찰함으로써 개체 컨텍스트를 다시 열지 않고이 문제를 해결할 수있었습니다. 나는 당신의 세그먼트 및 그룹을 다루는 경우

는 예를 들어, 내가이 후 segmentGroup으로 아무것도 할 않을거야 다음

Segment segment = repo.Find<Segment>(segmentId); 
var segmentGroup = segment.Group; 

의 어떤 것, 단순히 그것을 관찰하기 때문에 , 이제 존재합니다. 이전 관찰이 없었다면이 시스템은 여분의 호출이 데이터베이스에 전달되지 않았기 때문에이를 처리하는 방법을 알지 못했지만이 인스턴스에서 관찰 되었기 때문에 Group 객체의 데이터는 Segment 객체와 연관되어 있습니다.

이상한, 알고 있습니다 ... 존재하지만 존재하지 않습니다 ... 우리는 그것이 존재한다는 것을 압니다 만, 그것을 증명하기 위해 그것을 봐야합니다 ... 그래서 나는 왜이 시나리오를 슈뢰딩거의 것으로 언급합니까? 코드 ...

관련 문제