2010-11-27 5 views
7

저는 Linq 2 SQL을 Entity Framework로 전환했으며, 누군가가 도와 줄 수 있기를 희망하는 EF의 이상한 동작을보고 있습니다. 인터넷 검색을 시도했지만이 같은 문제로 다른 사람을 찾을 수 없었습니다. 상황을 설명하기 위해 시나리오를 조롱했습니다.엔티티 프레임 워크 및 리포지토리 패턴 (IQueryable 문제)

EF 컨텍스트에서 직접 작업 할 경우 select 내에서 select를 수행 할 수 있습니다. 내가 저장소가 된 IQueryable (또는 ObjectSet 또는하여 ObjectQuery를) 반환 저장소 패턴을 사용하는 경우, 나는 방법을 인식하지 못하는 엔티티에 NotSupportedException이 (LINQ를 얻을

 // this is an Entity Framework context that inherits from ObjectContext 
     var dc = new MyContext(); 

     var companies1 = (from c in dc.Companies 
          select new { 
           Company = c, 
           UserCount = (from u in dc.CompanyUsers 
              where u.CompanyId == c.Id 
              select u).Count() 
          }).ToList(); 

그러나 예를 들어, 다음은 완벽하게 정상적으로 실행 'System.Linq.IQueryable`1가) ... 여기

내 저장소의 예는 다음과 같습니다

public class Repository { 
    private MyContext _dc; 

    public Repository() { 
     _dc = new MyContext(); 
    } 

    public IQueryable<Company> GetCompanies() { 
     return _dc.Companies; 
    } 

    public IQueryable<CompanyUser> GetCompanyUsers() { 
     return _dc.CompanyUsers; 
    } 
} 

// 내 서비스 계층에서 예 (다른 클래스 내부 저장소를 사용하고 있습니다)

 var repository = new Repository(); 

     var companies2 = (from c in repository.GetCompanies() 
          select new { 
           Company = c, 
           UserCount = (from u in repository.GetCompanyUsers() 
              where u.CompanyId == c.Id 
              select u).Count() 
          }).ToList(); 

위의 코드는 NotSupportedException을 throw합니다.

나는 회사 및 CompanyUsers 간의 연관이 있는지, 나는 단순히이 작업을 수행 할 수 있다는 것을 깨닫고 그것을 잘 작동합니다

 var companies3 = (from c in repository.GetCompanies() 
          select new { 
           Company = c, 
           UserCount = (from u in c.CompanyUsers 
              select u).Count() 
          }).ToList(); 

을 ...하지만 내 예는 더 복잡 단지 단순화 된 버전입니다 엔티티간에 연관이없는 시나리오.

그래서 Entity Framework에서 NotSupportedException을 던지는 이유가 매우 혼란 스럽습니다. 어떻게 EF 컨텍스트에서 직접 작업 할 때 쿼리가 완벽하게 작동하지만 다른 메서드에서 반환 된 IQueryable을 사용하여 작업하는 경우에는 지원되지 않습니다. 이것은 Linq 2 SQL과 완벽하게 작동하지만 Entity Framework에서는 작동하지 않습니다.

어떤 통찰력이라도 대단히 감사하겠습니다.

미리 감사드립니다.

답변

7

나는 어떤 일이 벌어지고있는지는 EF가 이 EF 컨텍스트가 아니기 때문에 첫 번째 select에 대한 람다 내부의 repository.GetCompanyUsers() 표현식을보고 무엇을해야할지 모릅니다. IQueryable을 반환하는 식 대신 직접 IQueryable을 전달하면 작동해야한다고 생각합니다.

방법에 대해이 작업을 수행 할 경우 :

var companyUsers = repository.GetCompanyUsers(); 
    var companies2 = (from c in repository.GetCompanies() 
         select new { 
          Company = c, 
          UserCount = (from u in companyUsers 
             where u.CompanyId == c.Id 
             select u).Count() 
         }).ToList(); 
+0

우리는 왜 그런 식으로해야할까요, 여기에 연관성이 있습니까? – paragy

+0

+1 U 역시 대답했습니다 .. – paragy

+0

이 작업은 서버에 두 번 왕복을 필요로하지만 ... 잠깐입니까? –

3

이 SQL/EF에 Linq에있는 사람 이상한 버릇 중 하나입니다. 분명히 그들은 getter 속성을 SQL로 변환하는 방법을 구현했지만 getter에서 번역 할 방법이 아닙니다. 을 SQL로 변환했습니다.

GetCompanyUsers() 대신 CompanyUsers과 같은 속성을 사용하면 효과가 있습니다.

이상한?

그래서 그 대신

public IQueryable<CompanyUser> GetCompanyUsers() { 
    return _dc.CompanyUsers; 
} 

의 당신이 할 수

public IQueryable<CompanyUser> CompanyUsers { 
    get { return _dc.CompanyUsers; } 
} 

과 같은 매개 변수가있는 쿼리가 (당신은 분명, 속성으로 할 수없는), 내 질문은 여기에 대답 보러 지금까지 : Custom function in Entity Framework query sometimes translates properly, sometimes doesn't

wheresselects도 속성에 포함 할 수 있습니다. 그들은 잘 번역 할거야.

public IQueryable<Article> LiveArticles { 
    get { return _dc.Articles.Where(a => !a.IsDraft); } 
} 

그것은 또한 당신이 필요로하는 매개 변수가있는 쿼리의 수를 줄일 수 있습니다 : 내가 기사 테이블과 블로그가 있다면 예를 들어, 그 온라인 상태가 아닌 일부 기사가 포함되어 있습니다.

+0

매우 이상하지만, 당신은 절대적으로 옳습니다. IQueryable을 반환하는 속성은 EF와 함께 작동합니다. Linq to SQL도 메소드를 사용했지만 EF가 구현하지는 않았을 것입니다. –

관련 문제