Entity Framework 7の多対多問合せ

c# entity-framework entity-framework-core

質問

私はhttp://ef.readthedocs.org/en/latest/modeling/relationships.htmlから得たこの例に従っています

class MyContext : DbContext
{
    public DbSet<Post> Posts { get; set; }
    public DbSet<Tag> Tags { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<PostTag>()
            .HasKey(t => new { t.PostId, t.TagId });

        modelBuilder.Entity<PostTag>()
            .HasOne(pt => pt.Post)
            .WithMany(p => p.PostTags)
            .HasForeignKey(pt => pt.PostId);

        modelBuilder.Entity<PostTag>()
            .HasOne(pt => pt.Tag)
            .WithMany(t => t.PostTags)
            .HasForeignKey(pt => pt.TagId);
    }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public List<PostTag> PostTags { get; set; }
}

public class Tag
{
    public string TagId { get; set; }

    public List<PostTag> PostTags { get; set; }
}

public class PostTag
{
    public int PostId { get; set; }
    public Post Post { get; set; }

    public string TagId { get; set; }
    public Tag Tag { get; set; }
}

今私の質問はどのようにTagId与えられた投稿を得るために私のクエリを構築するだろうか?何かのようなもの:

public List<Post> GetPostsByTagId(int tagId)
{
    //linq query here
}

これがEF7であることに留意してください。

受け入れられた回答

私の最初のアドバイスは、コレクションのプロパティをList<T>ではなくICollection<T>に変更することICollection<T> 。あなたはこの記事で本当に良い説明を見つけることができます。

今実際の問題に戻ると、これは私があなたの質問をする方法です:

public List<Post> GetPostsByTadId(int tagId)
{
    using(var context=new MyContext())
    {
      return context.PostTags.Include(p=>p.Post)
                             .Where(pt=> pt.TagId == tagId)
                             .Select(pt=>pt.Post)
                             .ToList();
    }
}

EF7はレイジーローディングをサポートしていないので、また、彼のソリューションで@Igorが推奨するように、 DbSetをコンテキスト内のPostTagsとして含める必要があるため、 Postナビゲーションプロパティを熱心にロードする必要があります。

 public DbSet<PostTags> PostTags { get; set; }

説明:

あなたのクエリはPostTagsテーブルからPostTagsます。なぜなら、特定のタグに関連するすべての投稿を見つけることができるそのテーブルにあるからです。 「 PostテーブルをInclude内部結合のようにする」を参照してください。 PostTagsによってTagIdPostsフィルタリングの間で結合を適用すると、必要な列が取得されます。 Selectコールでは、 Postテーブルの列のみが必要であることを示しています。

Includeコールを削除しても、それでも機能するはずです。 Includeを使用して、結合を行う必要があることを明示的に示していますが、 Selectと、EFのLinqプロバイダは、結果としてPosts列を取得するために暗黙的に結合を行う必要があることを知るのに十分です。


人気のある回答

db.Posts.Where(post => post.PostTags.Any(pt => pt.TagId == tagId));


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ