Entity Framework Many to Many works but Include does not

ef-code-first entity-framework linq many-to-many

Question

With these 3 tables, I have a conventional many-to-many relationship.

[Post] (
  [PostId] int, (PK)
  [Content] nvarchar(max)
   ...
)

[Tag] (
  [TagId] int, (PK)
  [Name] nvarchar
  ...
)

[TagPost] (
  [TagId] int, (PK, FK)
  [PostId] int (PK, FK)
)

Additionally, TagId and PostId have the corresponding PK and FK values defined on the tables. Then, in c#, I have these classes and mapping.

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

After that, I may ask them using this code.

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

The posts I was looking for are indeed returned by this join, but despite the Include being present, the returned posts lack the related tags. Could someone please let me know what I'm missing so I can get the tags back with the posts?

You're welcome.

1
4
3/21/2013 7:10:48 PM

Accepted Answer

the secondfrom is a guide.Join This results inInclude as mentioned in here and here, to be disregarded.Include similar projections and grouping is likewise disregarded for other LINQ methods.

Many-to-many relationships often cannot be fixed; instead, one-to-many or one-to-one relationships with at least one single reference at one end are the only ones that can. If you simulate thePosts and connectedTags Because the relationship is many-to-many, EF won't immediately build the relationship in memory, preventing the data from being imported appropriately into another type (anonymous or named).post.Tags The collection will remain bare.

To obtain,Include working, you need to get rid of the secondfrom based on your inquiry and use thewhere direct clause to thePost entity parameter, for instance as follows:

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

A filter was used.Tag The expression supplied into specifies property..Any which is a phrase that begins with aTag (t (as a parameter)

3
5/23/2017 12:22:01 PM

Popular Answer

Try putting all of your selections into an anonymous object (something like this)

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

Considering the comments on my previous response and the fact that EF is able to locate the associated entities but is unable to populate theTags collection The definition of the Tags object in the Post class, in my opinion, is where the problem resides.

Try taking away theHashset<> the constructors' initializer, andprivate the set declaration states:

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


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow