web-dev-qa-db-ja.com

LINQとLambdaを使って参加する/場所

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を使用するのが初めてなので、このクエリが正しいかどうかわかりません。

374
David

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
859
Daniel Schaffer

これには2つの方法があります。 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構文がよりきれいであると思います(私はどちらが最も読みやすいかによって2つの間で変わります)。

ただし、データベースに適切な外部キーがある場合(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をロードするとき、 '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

1つのLoadWithのセットに対して、同じ型または多数の異なる型に対して多数のDataLoadOptions呼び出しを行うことができます。あなたがこれをたくさんするならば、あなたはただキャッシュを考慮したいかもしれません。

64
Damian Powell

キーセレクターが正しくありません。それらは問題のテーブルの型のオブジェクトを取り、結合で使用するキーを返すべきです。私はあなたがこれを意味すると思います:

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

キーセレクタの一部としてではなく、後でwhere句を適用できます。

32
Mark Byers

Danielは構文の関係についてよく説明していますが、理解しやすくするためにこのドキュメントをチームのためにまとめました。これが誰かに役立つことを願っています enter image description here

27
Talspaugh27

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;}
}
6
Visser

私はこのようなことをしました。

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

それはのようなものかもしれません

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};
2
pepitomb

この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
0
Ahamed Ishak

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 };
0
mtngunay