首页 > 解决方案 > 如何使用 EF 核心查询从多对多模型中获取一些对象?

问题描述

我尝试这样做:

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

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

但它不起作用。Visual Studio 看不到此表达式“a.ArticleTags.Tag.TagValue”。我怎样才能做到正确?

下面是使用的类的实现:

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

标签: c#.net-coreentity-framework-core

解决方案


基本上Include也是ThenInclude唯一的作用是告诉 EF 在从数据库中请求数据时加载这些嵌套对象。它不允许您只是忽略它ArticleTag是对象列表的事实,并且您需要使用此类对象的可用方法之一。所以在这种情况下你想申请FindArticleTag列表。

编辑:

请参阅下面的完整示例。请注意,通过向 EF 指示模型之间的关系,我什至不需要费心包含数据(后示例)。

模型创建:

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

控制器:

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

如您所见,您可以从中间表开始更容易,不需要包含链 thst 将钻取数据。


推荐阅读