Entity Framework Many work for many, but Include is not

I have a typical many-to-many relationship with these three tables

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

And, TagId and PostId are the PK and FK installed in the tables, respectively. Then I have these classes and mapping in 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"); }); } 

Then I have this code to request them

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

This union returns the messages I was looking for, however the returned messages do not fill in the associated tags, although I have Include. Can someone help to indicate what I am missing so that I can return the message tags?

Thank you very much.

+4
source share
2 answers

The double from is the Join guide, which causes Include be ignored, as mentioned here and. Include also ignored for other LINQ methods like grouping and forecasts .

Correcting relationships usually does not work for many-to-many relationships, only for relationships that have at least one link to one of the ends - one-to-many or one-to-one. If you project Posts and its associated Tags onto another type (anonymous or named), the data will be loaded correctly, but since the relationship is many-to-many, EF will not create the relationship in memory automatically, t26> the collection will remain empty.

To get Include work, you must remove the second from from your query and apply the where clause directly to the Post entity parameter, like so:

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

The filter using the Tag property is specified in the expression passed to .Any , which is an expression with the Tag ( t ) parameter.

+3
source

try selecting everything 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(); 

Based on the feedback on my original answer and the fact that EF can find related objects, but it does not populate the Tags collection, I believe the problem is defining the Tags object in the Post class.

Try removing the Hashset<> initializer from the constructors and private from the declared set:

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

All Articles