[c#] Linq Select에서 튜플 만들기

Entity Framework 6.1.3을 사용하여 SQL Server 데이터베이스에서 데이터를 검색하는 C # 및 .NET Framework 4.5.1을 사용하고 있습니다.

나는 이것을 가지고있다:

codes = codesRepo.SearchFor(predicate)
      .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
      .ToList();

그리고 실행하면 다음 메시지가 표시됩니다.

LINQ to Entities에서는 매개 변수가없는 생성자와 이니셜 라이저 만 지원됩니다.

내가 찾은 모든 예제가 대부분이 예제와 같기 때문에 Tuple을 어떻게 만들어야하는지 모르겠습니다.

나는 이것을 시도했다 :

codes = codesRepo.SearchFor(predicate)
      .Select(c => Tuple.Create(c.Id, c.Flag))
      .ToList();

그리고이 오류가 발생합니다.

LINQ to Entities는 ‘System.Tuple`2 [System.String, System.Byte] Create [String, Byte] (System.String, Byte)’메서드를 인식하지 못하며이 메서드는 저장소 식으로 변환 할 수 없습니다.

어디에 문제가 있습니까?



답변

octavioccl대답 이 작동 하는 동안 먼저 쿼리 결과를 익명 유형으로 프로젝션 한 다음 열거 가능으로 전환하고 튜플로 변환하는 것이 좋습니다. 이렇게하면 쿼리가 데이터베이스에서 필요한 필드 만 검색합니다.

codes = codesRepo.SearchFor(predicate)
    .Select(c => new { c.Id, c.Flag })
    .AsEnumerable()
    .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
    .ToList();

참고 : 위의 규칙은 EF6에 적용됩니다. EF Core는 자연스럽게 튜플 생성자를 통해 튜플 (프로젝션 또는 조인 / 그룹 키로)을 지원합니다. 예를 들어 원래 쿼리는 간단히 작동합니다.

codes = codesRepo.SearchFor(predicate)
  .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
  .ToList();

그러나 Tuple.Create방법은 아닙니다 (EF Core 2.x).


답변

C # 7에 대한 업데이트 된 답변입니다. 이제 더 간단한 구문을 사용하여 ValueTuples를 만들 수 있습니다.

codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag })
.AsEnumerable()
.Select(c => (c.Id, c.Flag))
.ToList();

이제 튜플의 속성 이름을 지정할 수도 있습니다.

codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag }) // anonymous type
.AsEnumerable()
.Select(c => (Id: c.Id, Flag: c.Flag)) // ValueTuple
.ToList();

따라서 Item1 또는 Item2로 사용하는 대신 Id 또는 Flag로 액세스 할 수 있습니다.

익명과 튜플 중 선택 에 대한 더 많은 문서


답변

이 시도:

codes = codesRepo.SearchFor(predicate)
  .Select(c => Tuple.Create(c.Id, c.Flag))
  .ToList();

LINQ to 엔터티에서 허용되지 않는다는 알림을 받았습니다.

또 다른 옵션은 선택하기 전에 결과를 메모리로 가져 오는 것입니다. 이 작업을 수행하려는 경우 .AsEnumerable () 전에 모든 필터링을 수행하는 것이 좋습니다. 이는 전체 테이블을 다시 가져온 다음 필터링하는 것과는 반대로 원하는 결과 만 가져 오는 것을 의미하기 때문입니다.

codes = codesRepo.SearchFor(predicate).AsEnumerable()
  .Select(c => Tuple.Create(c.Id, c.Flag))
  .ToList();

뿐만 아니라 Tuple.Create (c.Id, c.Flag)는 튜플 유형에서 코드를 좀 더 명시 적으로 만들고 싶다면 new Tuple (c.Id, c.Flag)로 변경 될 수 있습니다.


답변

에서 엔티티에 LINQ 당신은 익명의 유형에 또는 당신이 사용할 수있는 발행 DTO.To 피할에 투사 할 수 있습니다 AsEnumerable확장 방법 :

codes = codesRepo.SearchFor(predicate).AsEnumerable().
      .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
      .ToList();

이 방법은 당신이 작업을 할 수 있습니다 Object로 Linq를 대신 엔티티에 Linq에를 너무 후 호출, 당신은 당신이 사용하는 need.The 장점 어떤에서 쿼리의 결과 투사 할 수 있습니다 AsEnumerable대신 ToListAsEnumerable쿼리를 실행하지 않습니다, 그것은 실행을 연기 보존 식품. 이러한 메서드 중 하나를 호출하기 전에 항상 데이터를 먼저 필터링하는 것이 좋습니다.


답변

나는 답을 찾았습니다.

codes = codesRepo.SearchFor(predicate)
      .ToList()
      .Select(c => Tuple.Create(c.Id, c.Flag))
      .ToList();


답변

이 방법을 사용하여이를 수행하고 비동기를 사용하십시오.

var codes = await codesRepo.SearchFor(predicate)
                    .Select(s => new
                    {
                        Id = s.Id,
                        Flag = s.Flag
                    }).FirstOrDefaultAsync();

                var return_Value = new Tuple<string, byte>(codes.Id, codes.Flag);


답변

내 두 센트 : 이것은 유형 이름으로 몇 번 나를 잡았습니다.

고개를 끄덕이는 몇 가지 예 :

    private Tuple<string, byte> v1()
    {
        return new Tuple<string, byte>("", 1);
    }

    private (string, int) v2()
    {
        return ("", 1);
    }

    private (string Id, byte Flag) v3()
    {
        return ("", 1);
    }

문안 인사.