实体框架多对多工作,但不包括



这三个表是典型的多对多关系

[Post] (
  [PostId] int, (PK)
  [Content] nvarchar(max)
   ...
)
[Tag] (
  [TagId] int, (PK)
  [Name] nvarchar
  ...
)
[TagPost] (
  [TagId] int, (PK, FK)
  [PostId] int (PK, FK)
)

和,TagId和PostId是相应表上设置的PK和FK等。然后是c#

中的类和映射
public class Post {
    public Post()
    {
        this.Tags = new HashSet<Tag>();
    }
    [Key]
    public int PostId { get; set; }
    ...
    public virtual ICollection<Tag> Tags { get; private set; }
}
public class Tag {
    public Tag()
    {
        this.Posts = new HashSet<Post>();
    }
    [Key]
    public int TagId { get; set; }
    ...
    public virtual ICollection<Post> Posts { get; private set; }
}
internal class MyDbContext : DbContext
{
    public DbSet<Post> Posts { get; set; }
    public DbSet<Tag> Tags { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Post>().ToTable("Post");
        modelBuilder.Entity<Tag>().ToTable("Tag");
        modelBuilder.Entity<Post>()
            .HasMany(x => x.Tags)
            .WithMany(x => x.Posts)
        .Map(x =>
        {
            x.ToTable("TagPost");
            x.MapLeftKey("PostId");
            x.MapRightKey("TagId");
        });
    }

然后我用这段代码来查询它们

var list = (from p in ctx.Posts.Include(p => p.Tags)
            from t in p.Tags
            where ... // some of my filter conditions
            select p).ToList();

这个连接确实返回我正在寻找的帖子,但是返回的帖子没有他们的相关标签填写,即使我有包含在那里。有人可以帮助指出我错过了什么,这样我就可以有标签也与帖子返回?

from是手动Join,导致此处和此处提到的Include被忽略。对于其他LINQ方法,如分组和投影,Include也被忽略。

关系固定通常不适用于多对多关系,只适用于在一端至少有一个引用的关系——一对多或一对一。如果您将Posts和相关的Tags投影到另一个类型(匿名或命名),则数据将被正确加载,但由于关系是多对多的,EF不会在内存中自动创建关系,因此post.Tags集合将保持空。

要使Include工作,您必须从查询中删除第二个from,并将where子句直接应用于Post实体参数,例如:

var list = (from p in ctx.Posts.Include(p => p.Tags)
            where p.Tags.Any(t => t.TagId == 1)
            select p).ToList();

通过Tag属性的过滤器在传递给.Any的表达式中指定,该表达式是一个以Tag (t)为参数的表达式。

尝试将所有内容选择为匿名对象(类似于这样)

var list = (
        from p in ctx.Posts
        from t in p.Tags
        where ... // some of my filter conditions
        select new {
            Posts = p,
            Tags = p.Tags
        })
    .ToList();

根据对我最初答案的反馈和EF可以找到相关实体的事实,但它未能填充Tags集合,我认为问题在于Post类中标签实体的定义。

尝试从构造函数中删除Hashset<>初始化器,从set声明中删除private:

public virtual ICollection<Tag> Tags { get; set; }

最新更新