【问题标题】:Improving performance of Linq to SQL list intersection提高 Linq to SQL 列表交集的性能
【发布时间】:2021-09-27 12:40:54
【问题描述】:

我这里有一些工作代码,但我真的担心它效率不高 - 但我想不出改进它的方法。有什么想法吗?

我们有IQueryable<Users> users,它从用户表中获取数据,实体框架将每个用户映射到单独的组织表,这是一对多的关系。我们还有一个List<string> orgCriteria,这是我们要过滤用户的组织列表。本质上,我们希望获得在条件中的任何组织中具有成员资格的用户列表。

要将用户的组织名称与过滤条件中的组织进行比较,我们必须使用一些 linq/EF 映射,如下所示:var x = users.Select(x => x.Orgs.Name).ToList(); 但是,显示名称是我们从条件中得到的,这意味着我们还必须将部分名称转换为显示名称...

这些是涉及到所有这些的表:UserOrgsUserOrgs。用户对OrgsId 有一个FK,UserOrgs 有3 列:IdUserIdOrgId 其中UserIdOrgId 是它们各自表的FK。一个用户可以有 0 个或与 Orgs 一样多。每个组织都有一个名称,但我们通常在域模型中映射的显示名称由三列组成:namefoobar,其中bar 是可空列。

我尝试了这样的相交,但它不起作用:users = users.Where(x => x.Select(y => string.Format("{0} - {1}{2}", y.Org.Name, y.Org.foo, y.Org.bar != null ? " - " + y.Org.bar : string.Empty)).Intersect(orgCriteria).Any()); 因为我收到此错误:

在查询的 LINQ to SQL 实现中不能使用本地序列 除包含运算符之外的运算符。

所以我可以通过结合 foreach 和 intersect 使其工作,但我担心...如果我们有 500 个用户,每个用户有 20 个组织,这似乎是一个非常昂贵的过滤器。

这种方式行得通,但让我很紧张:

foreach(var user in users)
{
    List<string> userOrgNames = user.Orgs.Select(x => string.Format("{0} - {1}{2}", y.Org.Name, y.Org.foo, y.Org.bar != null ? " - " + y.Org.bar : string.Empty)).ToList();

    if (!userOrgNames.Intersect(orgCriteria).Any())
        users = users.Where(x => x.Id != user.Id);
}

有什么想法吗?

编辑 - 这是一个基本的图表!

【问题讨论】:

  • 请显示两组数据的文本或视觉表示,以及预期的结果。我不明白这个问题 - 显示输入和预期输出可能有助于我的弱脑。
  • 将整个列表作为单个表参数传递,不确定它是否在 EF 中得到适当支持,请参阅stackoverflow.com/questions/8157345/…,除非 XML、JSON 或 CSV 可能是前进的方向,因为它只是一个简单的字符串列表
  • 或者我在这里误解了一些东西:你为什么需要ToList,为什么你需要foreach,如果所有数据都是服务器端的,那么构建一个完整的LINQ查询到得到你想要的
  • 我添加了一个图表,希望能帮助我们直观地了解正在发生的事情!

标签: c# sql asp.net linq entity-framework-4


【解决方案1】:

您可以尝试以下方法。

我根据In essence we want to get a list of users who have a membership in any of the organizations in the criteria.这个声明做了这个LINQ

var filteredUsers = users.Where(user => 
             user.Orgs.Any(org => orgCriteria.Contains($"{org.Name} - {org.foo}{org.bar}")));

如果$"{org.Name} - {org.foo}{org.bar}" 不起作用,请使用string.Format("{0} - {1}{2}", org.Name, org.foo, org.bar)

【讨论】:

  • 我确实试过了——我必须修改它,因为用户有很多组织,所以你必须像 user.Orgs.org 而不是 user.orgs 那样做。前者在 UserOrgs 表级别查询数据,而后者在 Orgs 表查询数据,因此您必须再驱动一个级别来获取 name、foo 和 bar 属性。但主要问题是 string.format(任一版本)没有等效的 sql,因此会生成错误。
  • 能否请您向我们展示用户实体属性,我认为我们不需要user.Orgs.org。而关于字符串连接,我们可以直接使用普通字符串 Concat 即 (org.Name + " - " + org.foo + org.bar)
  • 我在问题中添加了一个基本图表,如果有帮助请告诉我!
  • userorgs 是否拥有Orgs 的属性?我们可以以user.userorgs.FirstOrDefault().org.Name 的身份访问org name 吗?
  • users是用户列表,userorgs有list属性,org有list属性,name、foo、bar是org的字符串属性。我无法得到这个建议,并且在 linq 中必须有一些选择,因为必须先访问这些列表中的每一个(用户组织的用户列表和用户组织的组织列表)才能获得到构成显示名称的详细信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 2012-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 2014-11-13
相关资源
最近更新 更多