0

I try to do it like this:

var articles = db.Articles.Include(at => at.ArticleTags)
                          .ThenInclude(t => t.Tag)
                          .ToList();

var articlesTag = articles.Where(a => a.ArticleTags.Tag.TagValue == "news").ToList();

But it dont work. Visual Studio does not see this expression "a.ArticleTags.Tag.TagValue". How can I do it right?

Here is the implementation of the classes used:

public class Tag
{
    public int Id { get; set; }
    public string TagValue { get; set; }
    public List<ArticleTag> ArticleTags { get; set; }
    public List<UserTag> UserTags { get; set; }

    public Tag()
    {
        ArticleTags = new List<ArticleTag>();
        UserTags = new List<UserTag>();
    }
}

public class Article
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Summary { get; set; }
    public List<ArticleTag> ArticleTags { get; set; }

    public Article()
    {
        ArticleTags = new List<ArticleTag>();
    }
}

public class ArticleTag
{
    public int ArticleId { get; set; }
    public Article Article { get; set; }

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

1 Answers1

1

Basically Include and ThenInclude only role is to tell EF to load those nested objects while asking for data from the database. It doesn't allow You just to ommit the fact that the ArticleTag is a list of objects and You need to use one of avaliable methods of such object. So in this case You want to apply Find to the ArticleTag list.

Edit:

See the complete example below. Note that by instructing EF about relationships between models it is not needed for me to even bother about including data (lat example).

Model creation:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            modelBuilder.Entity<Article>().HasData(
                new Article { Id = 1, Summary = "Article summary 1", Title = "Article title 1" },
                new Article { Id = 2, Summary = "Article summary 2", Title = "Article title 2" },
                new Article { Id = 3, Summary = "Article summary 3", Title = "Article title 3" },
                new Article { Id = 4, Summary = "Article summary 4", Title = "Article title 4" },
                new Article { Id = 5, Summary = "Article summary 5", Title = "Article title 5" },
                new Article { Id = 6, Summary = "Article summary 6", Title = "Article title 6" });

            modelBuilder.Entity<Article>().HasKey(a => a.Id);
            modelBuilder.Entity<Article>().HasMany(a => a.ArticleTags).WithOne(at => at.Article);

            modelBuilder.Entity<Tag>().HasData(
                new Tag { Id = 1, TagValue = "Tag 1" },
                new Tag { Id = 2, TagValue = "Tag 2" });

            modelBuilder.Entity<Tag>().HasKey(t => t.Id);
            modelBuilder.Entity<Tag>().HasMany(t => t.ArticleTags).WithOne(at => at.Tag);

            modelBuilder.Entity<ArticleTag>().HasData(
                new ArticleTag { ArticleId = 1, TagId = 1 },
                new ArticleTag { ArticleId = 2, TagId = 1 },
                new ArticleTag { ArticleId = 1, TagId = 2 },
                new ArticleTag { ArticleId = 2, TagId = 2 },
                new ArticleTag { ArticleId = 3, TagId = 1 },
                new ArticleTag { ArticleId = 4, TagId = 2 });

            modelBuilder.Entity<ArticleTag>().HasKey(at => new { at.ArticleId, at.TagId });
            modelBuilder.Entity<ArticleTag>().HasOne(at => at.Article).WithMany(a => a.ArticleTags);
            modelBuilder.Entity<ArticleTag>().HasOne(at => at.Tag).WithMany(t => t.ArticleTags);

            // Tag 1: Article 1,2,3
            // Tag 2: Article 1,2,4
            base.OnModelCreating(modelBuilder);
        }

Controller:

        public async Task<IActionResult> Index()
        {
            db.Database.EnsureCreated();
            var articles = db.Articles.Include(at => at.ArticleTags)
                          .ThenInclude(t => t.Tag);

            var articlesTag1 = articles.Where(a => a.ArticleTags.Any(at => at.Tag.TagValue == "Tag 1")).ToList();

            var articlesTag2 = articles.Where(a => a.ArticleTags.Any(at => at.Tag.TagValue == "Tag 2")).ToList();

            var articles1 = await db.ArticleTags.Include(at => at.Article)
                          .Include(at => at.Tag)
                          .Where(at => at.Tag.TagValue == "Tag 1").ToListAsync();

            var articles2 = await db.ArticleTags
                          .Where(at => at.Tag.TagValue == "Tag 2").ToListAsync();
            return View();
        }

As You can see You can make it far easier by starting from the middle table, not needed for including chain thst will drill for data.

Eatos
  • 444
  • 4
  • 12
  • Thanks. But I still did not understand how to get all the articles with the corresponding tag. You can give an example. – Andrew Kont Mar 08 '20 at 10:53
  • See the updated answer, I have created a complete example for You, checked only InMemory db. – Eatos Mar 08 '20 at 16:01