我有一个问题,我正在努力寻找答案。
我有 3 个具有类似关系的实体类(简化):
class Article {
public int id
public string Name
public int ArticleStandard Id
public int CompanyId
public ArticleStandard ArticleStandardNavigation
public Company CompanyNavigation
}
class ArticleStandard {
public int id
public ICollection<Article> Articles
}
class Company {
public in id
public ICollection<Article> Articles
}
所以关系是 1 个公司可以有很多文章,1 个标准文章可以有很多文章。它们都被设置为 DBContext 中的 DBSet。 给出的是 ArticleStandard 的 ID。我现在想通过article实体得到所有拥有这个标准article的公司。 我想“生产”的 TSQL 是:
select c.* from Company c
inner join Article a on c.ID = a.CompanyId
inner join ArticleStandard on a.ArticleStandard = arts.id
Where arts.Id = 1
这给出了我想要的结果。
我尝试了很多,我不想发布我所有的尝试来解决这个问题,这可以让它只与 Include 和 ThenInclude 一起工作。但我不想获得所有文章和文章标准。如果我只选择公司,则 Includes 将被忽略: https://learn.microsoft.com/en-us/ef/core/querying/related-data#ignored-includes
var vtp = context.Company.Include(a => a.Article).ThenInclude(ars => ars.ArticleStandardNavigation).ToList();
在这里,我什至难以在包含的实体上使用 where 子句。 我在这里读到了这个问题: How to add where clause to ThenInclude
但我无法让它真正起作用,尤其是只检索公司而不是其他实体。
我知道我可以加载所有内容,然后将这些公司排除在外。那行得通。但我想减少发送的数据量,并将查询保持为一个。
有什么提示吗?我对 EF Core 仍然缺乏经验,LinQ 有时也会让我感到困惑。
如果您需要更多信息或者可以指出类似的问题(我发现了一些类似的情况,但无法正确使用它们),我将非常感激。
感谢您的宝贵时间。
最佳答案
好吧,忘掉 SQL 和连接吧。在 EF (Core) 目标 LINQ 查询中,您使用导航属性来访问相关数据。在查询上下文中,实体表示数据库表记录和导航 - 连接和相关表记录。
对于引用导航属性,您可以使用简单的标准,例如:
Where(entity => entity.Reference.SomeProperty == someValue)
对于集合导航属性,通常是具有所需条件的Any
,例如:
Where(entity => entity.Collection.Any(related => related.SomeProperty == someValue))
换句话说,我希望记录中至少有一个具有此值的相关记录。
将上述规则应用于您的模型,等效查询将如下所示:
var query = db.Companies
.Where(c => c.Articles.Any(a => a.ArticleStandardNavigation.id == 1));
生成的 SQL 很可能与您手写的 SQL 不同(通常我们无法控制 ORM 的 SQL 生成),但结果应该是。
顺便说一句,无需将 Navigation
附加到导航属性名称。默认(且更直观)的约定是使用类名,例如
public class Article
{
// ...
public ArticleStandard ArticleStandard { get; set; }
public Company Company { get; set; }
}
关于c# - EF Core 选择一个由相关实体过滤的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49413045/