问题描述
因此,最初,我有这个查询,它带回了所有所需的相关信息,并获得了与该特定用户相关的报告的列表。
var reports = from r in Context.Reports
join ax in Context.AuthorizationXref on r.Id equals ax.ReportId
join g in Context.Groups on ax.GroupId equals g.Id
join ugx in Context.UsersGroupsXref on g.Id equals ugx.GroupId
where ugx.UserId == id
select r;
AuthorizationXref具有ReportID和GroupId。
public partial class AuthorizationXref
{
public int Id { get; set; }
public int ReportId { get; set; }
public int GroupId { get; set; }
public virtual Groups Group { get; set; }
public virtual Reports Report { get; set; }
}
public partial class Groups
{
public Groups()
{
AuthorizationXref = new HashSet<AuthorizationXref>();
UsersGroupsXref = new HashSet<UsersGroupsXref>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<AuthorizationXref> AuthorizationXref { get; set; }
public virtual ICollection<UsersGroupsXref> UsersGroupsXref { get; set; }
}
用户多对多组多对多报表(多对多是通过XREF完成的。)
虽然在这里,我将它放在700ms的基准上,这似乎确实很慢,但我意识到我对数据库至少执行了4次命中,所以我尝试这样做或多或少地等于相同的数据,但快了约7倍:
var repo = context.Reports
.Include(x => x.AuthorizationXref)
.ThenInclude(x => x.Group)
.ThenInclude(x => x.UsersGroupsXref)
.ToList();
这大约需要100ms的时间,但不会对userId进行任何过滤。这些基准测试是在开发环境中进行的,并且只会随着我们进入更高的环境而恶化,在更高的环境中,越来越多的报告被添加到用户中。我知道使用Selects效率更高,但是我找不到在实体上嵌套复杂的多对多选择的示例。
我可以说到这里为止,但是不知道在哪里放置其他步骤以更深入地研究对象。
var asdf = repo.Where(x=>x.AuthorizationXref.Any(y=>y.ReportId==x.Id));
最终目标是我需要一个由userId组成的报告列表,以删除ID在另一个表上显示的那些报告。因此,有一个名为UserReportFilter的表,它具有ReportId和UserId,该表中的任何报告都不应出现在我的最终结果中。
作为一个旁注,如果有人可以将我指向关于如何使用表达式的教程(最好是不假定读者完全了解所有内容的教程)的方向,我将不胜感激。我碰到了this article,学习像这样的东西似乎是很有意义的事情,但是在解释中我将需要更多的知识。我理解这个概念,并使用基本的Func返回值进行查询,但没有什么涉及面很广。
解决方法
我假设您在Reports和UserReportFilter表之间具有联系,因为您在UserReportFilter表中具有ReportId。下面的表达式应该起作用,
var reports = context.Reports
.Include(x => x.AuthorizationXref)
.ThenInclude(x => x.Group)
.ThenInclude(x => x.UsersGroupsXref)
.Include(x => x.UserReportFilters)
.Where(x => x.AuthorizationXref.Any(y => y.Group.UsersGroupsXref.Any(z => z.UserId==id))
.ToList();