c# - 如何使用 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; }
}
解决方案
基本上Include
也是ThenInclude
唯一的作用是告诉 EF 在从数据库中请求数据时加载这些嵌套对象。它不允许您只是忽略它ArticleTag
是对象列表的事实,并且您需要使用此类对象的可用方法之一。所以在这种情况下你想申请Find
到ArticleTag
列表。
编辑:
请参阅下面的完整示例。请注意,通过向 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 将钻取数据。
推荐阅读
- node.js - 寻找通过 ip 地址创建 HTTPS REST api 连接的方法(包括 SSL 证书)
- android - 我们什么时候在android测试中使用fail()方法?
- android - 限制用户在android拖放中将视图拖出布局
- beautifulsoup - 如何从 UL 和 LI 中提取值?
- php - 在 PHP 的范围内将 12 小时时间转换为 24 小时时间
- python - Python KivyMD:如何使 toggle_nav_drawer() 函数工作?
- scala - 用向量替换函数的参数
- hibernate - 如何在 Hibernate Java 中使用 @EmbeddedId 执行软删除?
- angular - Angular 7 LazyLoading 与孩子的孩子
- mysql - SQL 拉取行,其中一列在 72 小时内减少了 25%(另一列有日期)