2011-10-01 4 views
4

WCF RIA Services 및 Silverlight로 작업 해본 결과 ADO.NET 엔터티 데이터 모델에서 가져온 데이터를 제공하는 서비스를 제공하는 데 성공했습니다. 기존 SQL Server 2008 Express 데이터베이스에서 가져옵니다. 데이터베이스는 테이블 간의 많은 관계를 정의하여 데이터 바인딩을 위해 클라이언트 측을 사용할 수 있기를 희망합니다.lazy-loading 및 eager-loading 엔터티 참조가 예상대로 작동하지 않음

모든 나는 다음과 같은 서비스 방법을 실행하려고 할 때까지 순조롭게 진행되었다

public IQueryable<Timeline> GetHighlights() { 

    var self = from x in Database.Timelines 
       where User.Id == x.UserId || User.Id == x.SenderId 
       select x; 

    var friends = from x in Database.FriendItems 
        where User.Id == x.UserId 
        from y in Database.Timelines 
        where x.FriendId == y.UserId || x.FriendId == y.SenderId 
        select y; 

    return self.Concat(friends).OrderByDescending(s => s.Id); 
} 

참고 : '사용자가'현재 인증 된 사용자를 선택하고 데이터베이스는 단지 ObjectContext의 속성을 래핑 클래스의 내부 속성 (입니다 쉽게).

'Timeline'엔티티에는 'SilverfishUser'엔티티와 연결된 '사용자'및 '발신자'라는 두 가지 탐색 속성이 있습니다. 필자가 '자체'쿼리의 결과를 반복 할 때 이전에 언급 한 속성이 현재 사용자 (올바른)로 채워져 있음을 알 수 있습니다. 그러나 'friends'쿼리의 결과를 반복 할 때 두 속성 모두 null입니다 (클라이언트에 직렬화되기 전에).

내가 시도 설정 :

this.ContextOptions.LazyLoadingEnabled = false; 
//and 
this.ContextOptions.ProxyCreationEnabled = false; 

그리고 나는 또한 열망 - 로딩 쿼리 방법을 포함하여 참조를 시도 (게으른 로딩으로 모두 활성화 및 비활성화) 아무 소용.

다음 문을 사용하고 있었다 나는 성공적으로 타임 라인 개체의 사용자 및 보낸 사람 속성을 채운 유일한 방법 : 내가 이해에서

friends.ForEach(s => { 
    if (!s.UserReference.IsLoaded) s.UserReference.Load(); 
    if (!s.SenderReference.IsLoaded) s.SenderReference.Load(); 
}); 

은 별도의 쿼리의 '로드'연산 결과가 실행되는 데이터베이스에. 보시다시피, 사용자가 많은 타임 라인 게시물이있는 친구가 많으면 비효율적 인 상황이 발생할 수 있습니다. 게으른 로딩을 비활성화함으로써 피하려고하는 정확한 상황. 가능한 한 최소한의 쿼리로 바인딩 할 수있는 완전히로드 된 엔터티를 클라이언트에 반환하고 싶습니다.

도메인 서비스 마법사에서 생성 한 메타 데이터 속성 정의에 [Include] 특성을 적용하여 상대 속성이 클라이언트에 직렬화되지 않은 한 가지 문제를 이미 해결했습니다. 이 문제는 좀 더 복잡해 보입니다. 시도한 솔루션은 다른 사람들에 의해 널리 언급 되었기 때문에 이론적으로 내 문제를 해결해야하지만 그렇지 않습니다. 다시 말하지만, 엔티티를 성공적으로 채울 수있는 유일한 방법은 연관된 속성에 대해 생성 된 생성 된 EntityReference < 속성을 사용하여 참조를 명시 적으로로드하는 것입니다.

이 문제에 대한 도움, 경험 또는 정보는 크게 감사하겠습니다.

[편집] 내 연구의 일부에 대한 업데이트, 나는이 같은 쿼리를 수행 할 때 :. 탐색 속성을

var friends = Database.FriendItems 
       .Include("Friend.Timeline") 
       .Where(s => User.Id == s.UserId); 

를 액세스 ("friends.First() Friend.Timeline.First() .User ") 값이 null이 아닙니다.

.SelectMany(s => s.Friend.Timeline); 

내비게이션 속성에 더 이상 값이 없다는 것은 새로운 컬렉션으로 타임 라인을 선택했을 때뿐입니다. 이제 이것은 추측 일 뿐이지 만, 새 객체 인스턴스에 속성 값을 투영한다고 가정 할 수 있으므로 순환 참조를 피하기 위해 이러한 속성을 다시 채우지 않습니까?어쨌든, 이것은 해결할 피클 중 하나입니다. 다행히도 내가하는 것보다 더 많은 것을 알고있는 누군가가 있습니다.

답변

0

글쎄, 아주 우아한 방법은 아니지만 약간의 해결책을 찾을 수있었습니다. 나는 사람들이 그것을 볼 수 있도록 대답으로 게시 할 것이지만 가능한 한 질문을 공개하고 더 적절한 해결책을 제시 할 것입니다.

가 여기 내 수정의 :

public IQueryable<Timeline> GetHighlights() { 

    var self = from x in Database.Timelines 
       where User.Id == x.UserId || User.Id == x.SenderId 
       select x; 

    var friends = from x in Database.FriendItems.Include("Friend.Timeline") 
        where (User.Id == x.UserId) 
        select x.Friend.Timeline; 

    List<Timeline> highlights = new List<Timeline>(); 
    highlights.AddRange(self); 

    friends.ForEach(x => x.ForEach(y => highlights.Add(y))); 
    return highlights.AsQueryable().OrderByDescending(s => s.Id); 
} 

내가이 수동으로 새 컬렉션을 만드는 것입니다 작동하는 이유를 생각 , 나는 이렇게로드 된 관계형 속성을 유지, 새로운 개체로 예상되는 엔티티를 방지합니다. 다시 말하지만, 이것은 단지 추측이지만, 가정은 꽤 좋은 패턴을 따르고 있습니다.

관련 문제