.NET Core 3.0 Entity Framework에서 그룹 조인을 수행하는 방법은 무엇입니까?


13

.NET Core 3.0의 변경 사항으로 인해

... NavigationExpandingExpressionVisitor '가 실패했습니다. 이는 EF Core의 버그 또는 제한 사항을 나타낼 수 있습니다. 자세한 내용은 https://go.microsoft.com/fwlink/?linkid=2101433 을 참조 하십시오 .) ---> System.InvalidOperationException : LINQ 식 'GroupJoin, ...

이것은 매우 간단한 쿼리이므로 .NET CORE 3.0에서 수행 할 수있는 방법이 있어야합니다.

 var queryResults1 = await patients
            .GroupJoin(
                _context.Studies,
                p => p.Id,
                s => s.Patient.Id,
                (p, studies) => new 
                {
                    p.DateOfBirth,
                    p.Id,
                    p.Name,
                    p.Sex,
                   Studies =studies.Select(s1=>s1)
                }
            )
            .AsNoTracking().ToListAsync();

나는 기본적으로 Linq 쿼리 (또는 위와 같은 방법 구문)를 찾고 환자에 대한 연구를 연결하고 연구를 빈 목록으로 설정하거나 주어진 환자에 대한 연구가없는 경우 null을 설정합니다.

어떤 아이디어? 이것은 .NET Core 2.2에서 작동했습니다. 또한 위의 MSFT 링크는 주요 변경 사항이 클라이언트 측 평가와 관련이 있으며 생성 된 쿼리가 전체 테이블을 읽은 다음 클라이언트 측에 조인하거나 필터링해야하는 것을 피합니다. 그러나이 간단한 쿼리를 사용하면 조인을 쉽게 서버 측에서 수행 할 수 있습니다.

답변:


11

여기 에서 설명했듯이 데이터베이스에서 지원하지 않는 쿼리를 시도하고 있습니다. EF Core 2는 클라이언트 측 평가를 사용하여 코드를 작동 시켰지만 EF Core 3는 데이터 세트가 증가함에 따라 디버그하기 어려운 성능 문제가 발생하기 때문에 클라이언트 측 편의가 제공되므로 거부합니다.

을 사용 DefaultIfEmpty하여 환자의 연구에 참여한 다음와 수동으로 그룹화 할 수 있습니다 ToLookup.

var query =
    from p in db.Patients
    join s in db.Studies on p.Id equals s.PatientId into studies
    from s in studies.DefaultIfEmpty()
    select new { Patient = p, Study = s };

var grouping = query.ToLookup(e => e.Patient); // Grouping done client side

위의 예는 전체 환자 및 연구 엔터티를 가져 오지만 대신 열을 체리 픽으로 선택할 수 있습니다. 환자에게 필요한 데이터가 각 스터디에 대해 반복하기에 너무 큰 경우, 조인 된 쿼리에서 환자 ID 만 선택하고 나머지 환자 데이터는 별도의 비조 인 쿼리로 쿼리합니다.


2
답이 작동합니다! 쿼리 번역기에서 아직해야 할 일이 있다고 생각합니다. 이와 같은 간단한 쿼리는 번역 가능해야합니다. FK / 인덱스가 올바르다 고 가정 할 때 데이터 세트가 증가하므로 2 개의 테이블에 대한 간단한 그룹 조인에는 성능 문제가 없어야합니다. 많은 사람들이 tis 문제를 겪을 것으로 의심됩니다 .2 테이블 그룹 조인은 상당히 표준적이고 자주 사용되는 쿼리입니다.
shelbypereira

@ she72 동의합니다. 문제는 LINQ와 SQL이 "group"키워드를 사용하는 방식의 차이에서 비롯된 것 같습니다. EF Core는 LINQ groupby를 왼쪽 조인으로 변환해야 하는데 예상보다 많은 행을 되찾지 않습니다. 이에 따라 의견을 게시했습니다 .
Edward Brey

후속 질문이 있는데, 여전히이 유형의 쿼리에 대한 그룹화가 클라이언트 측에서 수행되어야하는 이유를 이해하려고 노력 중이며 새로운 LINQ 프레임 워크의 한계로 보입니다. 위의 경우 예기치 않은 방식으로 클라이언트 측 실행 속도가 느려질 위험이 없습니다. 당신은 명확히 할 수 있습니까?
shelbypereira

1
그리고 추가 후속 조치는 환자 당 1000 개의 연구가있는 경우 클라이언트 측을 그룹화하는 재구성 된 쿼리에서 DB에서 각 환자를 1000 회로드하는 것입니다. 이 작업을 DB에서 수행하고 그룹화 된 결과를 반환하는 대안이 있습니까?
shelbypereira

1
@ shev72 데이터베이스가 이해하는 유일한 그룹은 집계와 관련이 있습니다 (예 : 환자 당 연구 횟수가있는 환자의 쿼리). 데이터베이스는 항상 직사각형 데이터 셋을 반환합니다. 계층 그룹은 클라이언트에 의해 구성되어야합니다. 클라이언트 측 평가 또는 ORM의 일부로 볼 수 있습니다. 계층 적 그룹화에서 부모 엔터티 데이터는 다시 쿼리되지는 않지만 반복됩니다.
Edward Brey

0

정확히 같은 문제와 큰 어려움을 겪었습니다. .net Core 3.0은 메소드 구문 (아직?)에서 Join 또는 Groupjoin을 지원하지 않습니다. 재미있는 부분은 쿼리 구문에서 작동합니다.

이것을 시도하십시오. 조금 구문 구문이있는 쿼리 구문입니다. 이것은 왼쪽 외부 조인이 좋은 올바른 SQL 쿼리로 훌륭하게 변환되며 데이터베이스에서 처리됩니다. 나는 당신의 모델을 얻지 못했기 때문에 구문을 확인해야합니다 ....

var queryResults1 = 
    (from p in _context.patients
    from s in _context.Studies.Where(st => st.PatientId == p.Id).DefaultIfEmpty()
    select new
    {
        p.DateOfBirth,
        p.Id,
        p.Name,
        p.Sex,
        Studies = studies.Select(s1 => s1)
    }).ToListAsync();

그런데 Method syntac DO와의 Join 및 GroupJoin은 비 코어 프레임 워크 및 EF와 함께 작동합니다. 그리고 서버 측에있는 올바른 쿼리로 번역하십시오
hwmaat

1
studies.Select의 연구 (S1 => S1) 무엇
Ankur 로라

모델은 질문에 포함되지 않았으므로 연구 모델을 모릅니다. 가장 좋은 추측은 이것이 모델의 가상 모음이라는 것입니다.
hwmaat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.