Linq Select에서 튜플 만들기


87

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)'메서드를 인식하지 못하며이 메서드는 저장소 식으로 변환 할 수 없습니다.

어디에 문제가 있습니까?


강력한 형식의 개체를 만들어야하는 것 같습니다. 하지만 네, 좋은 질문입니다. 찬성.
frenchie

답변:


118

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).


아주 좋은 해결책-감사합니다! ...이 솔루션을 다른 nullable 값으로 확장해야한다면 어떨까요? .Select(c => new { c.Id, c.Flag, c.Foo?.Code })작동하지 않습니다.
skyfrog

2
@skyfrog 연산자 ?.는 표현식 트리에서 지원되지 않습니다. 하지만 그 외에는 원하는만큼의 값으로 익명 유형을 확장 할 수 있습니다. 필요할 때 이름을 지정하는 것을 잊지 c => new { c.Id, c.Flag, Code = (int?)c.Foo.Code }
마십시오.

1
큰! 답장을 보내 주신 @Ivan에게 감사드립니다. 너무 가까웠어요! 다시 ;-) 보면서 ... 그러나 그것은 항상 쉬운 말을하는 것입니다
skyfrog

좋은 대답, EF-Entities와 함께 사용할 수 있습니다 .. 예 : dbCtx.MyEntity.Where (). Select (.. to anon object ...). etc ...
joedotnot

44

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로 액세스 할 수 있습니다.

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


11

이 시도:

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)로 변경 될 수 있습니다.


죄송합니다. 작동하지 않습니다. 자세한 내용으로 질문을 업데이트했습니다.
VansFannel 2015

11

에서 엔티티에 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쿼리를 실행하지 않습니다, 그것은 실행을 연기 보존 식품. 이러한 메서드 중 하나를 호출하기 전에 항상 데이터를 먼저 필터링하는 것이 좋습니다.


5

나는 답을 찾았습니다.

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

아니요. SELECT *
Mihai Bratulescu

1

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

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);

0

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

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

    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);
    }

문안 인사.


게시 한 구문이 작동하지 않습니다. 당신이 쓰려고했던 것은 아마도 public (string Id, byte Flag) SearchFor(Expression predicate)이지만 이것은 요점을 벗어났습니다. 2 센트는 답이 아니라 의견입니다.
M.Stramm

2
내 답변을 업데이트했습니다. 게시하기 전에 확인 했어야합니다. 동의하지 않습니다. 모든 정보는 위치에 관계없이이 페이지를 방문하는 모든 방문자에게 유용합니다. 댓글은 답변 덕분에 답변뿐만 아니라 의도도 전달하지 않습니다.
IbrarMumtaz

추가 된 콘텐츠가 좋고 댓글이 코드 예제에 적합하지 않다는 데 동의합니다. 편집 해 주셔서 감사합니다. 이제 이것이 OP의 질문에 대한 답이 아니라는 것이 분명합니다 (그러나 튜플 관련 문제에 도움이 될 수 있습니다).
M.Stramm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.