如何更高效地编写C# Lambda查询

4
有没有办法缩短这三个lambda表达式?现在我需要三个步骤才能得到结果。
首先,我查找所有属于“某人”的目标。然后,我在链接表中查找所有属于这些目标的projectId。最终的lambda通过它们的id返回所有项目。
我不禁想到有一种更有效率的方法,但我似乎找不到...
public async Task<List<Project>> GetProjectsFromSomeone(string someone) {
    var targetIds = from target in Context.Targets
                     where target.Someone.ToLower().Contains(someone.ToLower())
                     select target.Id;

    var projectIds = from pt in Context.ProjectTargets
                 where targetIds.Any(id  => id == pt.TargetId)
                 select pt.ProjectId;

    var projects = from prj in Context.Projects
                where projectIds.Any(id => id == prj.Id)
                select prj;

    return await projects.ToListAsync(); 
}

public class ProjectTarget
{
    public int ProjectId { get; set; }
    public int TargetId { get; set; }

    public Project Project { get; set; }
    public Target Target { get; set; }
}

public class Target
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Someone { get; set; }
}

public class Project
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
}

首先,如果你只是将第二个查询语句中的 select pt.ProjectId 改为 select pt.Project,那么第三个查询语句就没有用了。 - Camilo Terevinto
尽管您在三个步骤中创建查询,但只进行了一次对数据库的调用。您可以使用导航属性或连接将其重写为一个查询语句,但很可能具有相同的运行时间。所以我想这取决于您对效率的定义。 - juharr
提出建议,如果可以的话,在字符串比较中不要使用 .ToLower()。.ToUpper() 或 .ToUpperInvariant() 是首选,如果您还使用 CultureInfo 来精确定义匹配,则更好。 - CDove
1
@CDove 使用 ToUpperInvariant 或带有 CultureInfo 的重载是无效的,因为这是被翻译成 SQL 的 EF。大多数数据库通常具有不区分大小写的排序规则,因此可能根本不需要进行大小写转换。 - juharr
2个回答

6
您可以使用 Linq 连接。Linq 将处理连接和 where 条件。
public async Task<List<Project>> GetProjectsFromSomeone(string someone) 
{    
    var projects = from target in Context.Targets
                join pt in Context.ProjectTargets on target.Id equals pt.TargetId
                join prj in Context.Projects on pt.ProjectId equals prj.Id
                where target.Someone.ToLower().Contains(someone.ToLower())
                select prj;
    return await projects.ToListAsync(); 
}

希望这能有所帮助!

1
OP正在执行的是Contains而不是Equals。此外,您无法控制EF查询的大小写敏感性,因为它会被转换为SQL,并且这将由数据库的排序规则确定。 - juharr

1

我认为你可以使用连接查询。

from P in Context.Projects
join PT in Context.ProjectTargets on P.Id equals PT.id
join T in Context.Targets on PT.TargetId equals T.id
  .Select(m => new
  {
      //select the fields which you want select
  });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接