LINQ 및 Lambda와의 결합 / 위치


457

LINQ 및 Lambda로 작성된 쿼리에 문제가 있습니다. 지금까지 내 코드에 많은 오류가 발생했습니다.

int id = 1;
var query = database.Posts.Join(database.Post_Metas,
                                post => database.Posts.Where(x => x.ID == id),
                                meta => database.Post_Metas.Where(x => x.Post_ID == id),
                                (post, meta) => new { Post = post, Meta = meta });

LINQ를 처음 사용 하므로이 쿼리가 올바른지 확실하지 않습니다.


11
무엇을 이루려고 노력하고 있습니까?
Germán Rodríguez

4
문장에서 쿼리가 무엇을 하시겠습니까?
사냥꾼

6
키 선택기하는 방법이 너무 복잡합니다. id로 선택하려면 x => x.ID 만 있으면됩니다.
Eric Lippert

1
데이터베이스 및 해당 게시물의 메타 데이터에서 게시물을 얻고 싶었습니다.
David

답변:


1056

SQL 구문에 익숙하다면 LINQ 쿼리 구문을 사용하는 것이 훨씬 명확하고 자연스럽고 오류를 쉽게 발견 할 수 있습니다.

var id = 1;
var query =
   from post in database.Posts
   join meta in database.Post_Metas on post.ID equals meta.Post_ID
   where post.ID == id
   select new { Post = post, Meta = meta };

그래도 람다를 계속 사용하고 있다면 구문이 약간 벗어납니다. LINQ 확장 방법을 사용하는 동일한 쿼리는 다음과 같습니다.

var id = 1;
var query = database.Posts    // your starting point - table in the "from" statement
   .Join(database.Post_Metas, // the source table of the inner join
      post => post.ID,        // Select the primary key (the first part of the "on" clause in an sql "join" statement)
      meta => meta.Post_ID,   // Select the foreign key (the second part of the "on" clause)
      (post, meta) => new { Post = post, Meta = meta }) // selection
   .Where(postAndMeta => postAndMeta.Post.ID == id);    // where statement

10
@Emanuele Greco, 편집에 대해 "ID 필드의 동일성은 JOIN 조건으로 설정됩니다. WHERE 절을 사용할 필요가 없습니다!": WHERE 절은 ID 필드간에 동등성을 테스트하지 않고 게시물 ID 간의 동등성을 테스트합니다 쿼리 외부에 선언 된 열 및 id 매개 변수
Daniel Schaffer

9
의 멋진 조각 lambda과 쉽게 사용하고 이해하는 견적입니다
피오트르 쿨라

1
멋진 예
장난감

1
람다에 대한 설명은 람다로 작성되기도합니다. 잘 설명했다.
Pinch

80

이 두 가지 방법으로 갈 수 있습니다. 사용 LINQPad 와 더미 데이터베이스, 나는 다음과 같은 쿼리를 내장 (당신이있는 거 LINQ에 새로운 경우 귀중한를)

Posts.Join(
    Post_metas,
    post => post.Post_id,
    meta => meta.Post_id,
    (post, meta) => new { Post = post, Meta = meta }
)

또는

from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }

이 특별한 경우에는 LINQ 구문이 더 깨끗하다고 ​​생각합니다 (읽기 가장 쉬운 것에 따라 둘 사이에서 변경됩니다).

내가 지적하고 싶은 것은 데이터베이스에 적절한 외래 키 (post와 post_meta 사이)가 있다면 많은 수의 레코드를로드하려고하지 않으면 명시 적 조인이 필요하지 않을 것입니다 . 귀하의 예는 단일 게시물을로드하려고하고 메타 데이터임을 나타냅니다. 각 게시물에 대해 많은 post_meta 레코드가 있다고 가정하면 다음을 수행 할 수 있습니다.

var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();

n + 1 문제를 피하려면 LINQ to SQL에 모든 관련 항목을 한 번에로드하도록 명시 적으로 지시 할 수 있습니다 (L2S에 더 익숙한 경우 고급 주제 일 수 있음). 아래 예는 "포스트를로드 할 때 'Post_metas'속성으로 표시되는 외래 키를 통해 이와 관련된 모든 레코드도로드합니다"라고 말합니다.

var dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Post>(p => p.Post_metas);

var dataContext = new MyDataContext();
dataContext.LoadOptions = dataLoadOptions;

var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically

동일한 유형 또는 여러 유형 LoadWith에 대해 단일 세트에서 많은 호출을 수행 할 수 DataLoadOptions있습니다. 이 작업을 많이 수행하면 캐싱을 고려할 수 있습니다.


1
LinqPad CRM 2016 ?
Kiquenet

49

Daniel은 구문 관계에 대해 잘 설명했지만 팀이 이해하기 쉽도록이 문서를 정리했습니다. 이것이 누군가를 돕기를 바랍니다.여기에 이미지 설명을 입력하십시오


우리가 여기있는 것처럼 단순히 값 목록을 처리 할 때는 작동하지 않습니다. 객체에 id 속성이 없습니다.
Talspaugh27

이것이 실제로 유용하다는 것을 알았지 만 조인 열을 추가 해야하는 오류가 발생했습니다. @Mark Byers가 게시 한 답변을 보면 조인 열에는 Post_ID두 번째 별칭 의 필드가 meta => meta.Post_ID있습니다. 이 그림의 예에서 g.id원래 select 문의 일부 JOIN gStatus g on g.id는 최종 Lambda 표현식에 복제되지 않습니다.
SausageFingers

3
OP가 게시 한 답변에 필요한 실제 linq에 대한 참조로 이것을 게시하려고 시도하지 않았습니다 .SQL을 Linq 형식으로 이동하는 방법에 대한 참조의 일부 였으므로 입력 내용이 원래 질문과 약간 다릅니다. gStatus 값에 대한 클래스를 만든 경우 id 속성을 넣은 다음 예 = g => g.id와 결합했을 것입니다. 가능한 한 코드를 간단하게 유지하기 위해 값 목록을 사용했습니다.
Talspaugh27

@ Talspaugh27 그렇다면 왜 SQL 쿼리에서 g.id의 gStatus에 가입합니까? 실수입니까, 아니면 의도적인가요?
Drammy

SQL 테이블의 @ Drammy 각 열에는 이름이 있어야 하므로이 ID를 보유하기위한 엄격하게 1 열 테이블이기 때문에 id라는 열을 사용했습니다 .List <int>에는 그 문제가 없습니다. 내가 그 상태로 설정 public class IdHolder{ int id } 한 다음 gStatus에서 해당 객체를 사용 List<IdHolder> gStatus = new List<IdHolder>(); gStatus.add(new IdHolder(){id = 7}); gStatus.add(new IdHolder(){id = 8}); 하면 Linq가 변경되어 t =>t.value.TaskStatusId, g=>g.id 해당 변경이 의미가 있습니까?
Talspaugh27

37

키 선택기가 잘못되었습니다. 해당 테이블 유형의 오브젝트를 가져 와서 조인에 사용할 키를 리턴해야합니다. 나는 당신이 이것을 의미한다고 생각합니다 :

var query = database.Posts.Join(database.Post_Metas,
                                post => post.ID,
                                meta => meta.Post_ID,
                                (post, meta) => new { Post = post, Meta = meta });

나중에 키 선택기의 일부가 아닌 where 절을 적용 할 수 있습니다.


9

LINQ + EntityFramework를 시작할 때이 예제를 하루 동안 보았습니다.

EntityFramework를 사용 Meta하고 있고 Post모델 객체 에 이름이 지정된 탐색 속성 이 있으면이 작업은 쉽게 수행 할 수 있습니다. 엔터티를 사용 중이고 해당 탐색 속성이 없으면 무엇을 기다리고 있습니까?

database
  .Posts
  .Where(post => post.ID == id)
  .Select(post => new { post, post.Meta });

먼저 코드를 수행하는 경우 속성을 다음과 같이 설정합니다.

class Post {
  [Key]
  public int ID {get; set}
  public int MetaID { get; set; }
  public virtual Meta Meta {get; set;}
}

5

나는 이와 같은 일을했습니다.

var certificationClass = _db.INDIVIDUALLICENSEs
    .Join(_db.INDLICENSECLAsses,
        IL => IL.LICENSE_CLASS,
        ILC => ILC.NAME,
        (IL, ILC) => new { INDIVIDUALLICENSE = IL, INDLICENSECLAsse = ILC })
    .Where(o => 
        o.INDIVIDUALLICENSE.GLOBALENTITYID == "ABC" &&
        o.INDIVIDUALLICENSE.LICENSE_TYPE == "ABC")
    .Select(t => new
        {
            value = t.PSP_INDLICENSECLAsse.ID,
            name = t.PSP_INDIVIDUALLICENSE.LICENSE_CLASS,                
        })
    .OrderBy(x => x.name);

4

그것은 같은 것일 수 있습니다

var myvar = from a in context.MyEntity
            join b in context.MyEntity2 on a.key equals b.key
            select new { prop1 = a.prop1, prop2= b.prop1};

1

1은 1 개의 2 개의 다른 테이블 조인과 같습니다.

var query = from post in database.Posts
            join meta in database.Post_Metas on 1 equals 1
            where post.ID == id
            select new { Post = post, Meta = meta };

1

이 linq 쿼리가 도움이 될 것입니다. 메타가 포함 된 모든 게시물을 가져옵니다.

var query = database.Posts.Join(database.Post_Metas,
                                post => post.postId, // Primary Key
                                meta => meat.postId, // Foreign Key
                                (post, meta) => new { Post = post, Meta = meta });

동등한 SQL 쿼리

Select * FROM Posts P
INNER JOIN Post_Metas pm ON pm.postId=p.postId

세 번째 매개 변수 다음에 괄호를 닫았습니다 ... "Join에 대한 과부하가 세 가지 인수를 취하지 않습니다"
LastTribunal

3
이것은 인정 된 답변과 동일합니다. 7 년 후 -1
reggaeguitar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.