【问题标题】:Filtering with EF Core through multiple nested object relationships通过多个嵌套对象关系使用 EF Core 进行过滤
【发布时间】:2020-08-27 14:30:36
【问题描述】:

我有一项新要求,即根据属于黑名单的内容过滤来自查询的报告返回。

所以最初我有这个查询,它会带回所需的所有相关信息并获取与该特定用户关联的报告列表。

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

用户多对多组多对多报告(多对多通过外部参照完成)。

在这里,我将其设置为 700 毫秒,这似乎真的很慢,我意识到我至少对数据库进行了 4 次点击,所以我尝试这样做,这或多或少地达到了相同的数据,但速度快了约 7 倍:

    var repo = context.Reports
        .Include(x => x.AuthorizationXref)
        .ThenInclude(x => x.Group)
        .ThenInclude(x => x.UsersGroupsXref)
        .ToList();

这在大约 100 毫秒时进行了测试,但不会对 userId 进行任何过滤。这些基准在 Dev 中,只会随着我们进入更高的环境而恶化,越来越多的报告被添加给用户。我知道使用 Selects 更有效,但我找不到实体上复杂的嵌套多对多选择的示例。

我可以做到这一点,但不知道在哪里放置其他步骤以深入了解对象。

var asdf = repo.Where(x=>x.AuthorizationXref.Any(y=>y.ReportId==x.Id));

最终目标是我需要按 userId 列出的报告列表,删除那些按 ID 显示在另一个表上的报告。所以有一个名为 UserReportFilter 的表,它有 ReportId 和 UserId,该表中的任何报告都不应该出现在我的最终结果中。

作为旁注,如果有人可以向我指出如何使用表达式的教程(最好是不假定读者完全了解所有内容的教程),我将不胜感激。我遇到了this article,学习这样的东西似乎很强大,但是我需要更多的解释。我理解这个概念,并且我使用基本的 Func 返回进行查询,但没有那么广泛。

【问题讨论】:

    标签: c# entity-framework-core linq-to-entities


    【解决方案1】:

    我假设您在 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();
    

    【讨论】:

    • 我没有从智能感知中的 AuthorizationXref 获得 Group,因为它是一个集合......我想我应该更清楚。
    • 你能分享你的 AuthorizationXref.cs 类吗?如果它是一个集合,你应该能够得到它
    • 我添加了一个类,另一个类几乎相同。这是我对 EF 和 Core 的首次重大尝试。拥有大量嵌套集合从来都不是我需要做的事情,而存储过程通常是这类事情的 goto,但我试图在这个项目中不使用它。
    • Intellisense 可能会在 .ThenInclude() 上出现故障,但如果拼写正确,错误应该会消失。 AuthorizationXref.cs 似乎包含 Group 是正确的
    • 嗯,这是最好的方法和过滤器。但也有点关于性能。我以为我以前尝试过 .Any ,但显然没有。它现在给了我正确的计数,并且运行时间约为 75 毫秒,这是一个巨大的改进。谢谢你。我只需要验证它是否为我提供了正确的 65 份报告,但它似乎应该。您可能希望将新的 where 合并到后代的答案中。
    猜你喜欢
    • 2022-12-22
    • 1970-01-01
    • 2020-07-03
    • 2021-12-17
    • 2014-10-14
    • 1970-01-01
    • 2021-06-10
    • 2021-05-26
    • 1970-01-01
    相关资源
    最近更新 更多