gpt4 book ai didi

c# - 如何避免在 C# LINQ 中连续嵌套 .Any

转载 作者:太空狗 更新时间:2023-10-29 21:43:37 25 4
gpt4 key购买 nike

我有一个收藏列表 BossList。因为我使用嵌套的 .Any() 来确定条件。现在我的真实项目中的性能非常慢。请考虑以下示例源代码。

void Main()
{

List<Boss> BossList = new List<Boss>()
{
new Boss()
{
ID = 101,
Name = "Harry",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>() {
new Person() {
ID = 101,
SID = 102,
Name = "Peter",
Department = "Development",
Gender = "Male",
Role = "Assistant",
PayInfo = new List<PayrollInfo>()
{
new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 6 },
new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 2 },
new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 6 },
new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 8 },
new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 9 },
new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 },
}
},
new Person() {
ID = 101,
SID = 103,
Name = "Emma Watson",
Department = "Development",
Gender = "Female",
Role = "Assistant",
PayInfo = new List<PayrollInfo>() {
new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 5 },
new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 9 },
new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 2 },
new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 },
}
},

}
},
new Boss()
{
ID = 104,
Name = "Raj",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>()
{
new Person() {
ID = 104,
SID = 105,
Name = "Kaliya",
Department = "Development",
Gender = "Male",
Role = "Assistant",
PayInfo = new List<PayrollInfo>() {
new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 6 },
new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 2 },
new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 6 },
new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 8 },
new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 9 },
new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 },
}
},
new Person() {
ID = 104,
SID = 103,
Name = "Emma Watson",
Department = "Development",
Gender = "Female",
Role = "Assistant",
PayInfo = new List<PayrollInfo>() {
new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 5 },
new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 9 },
new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 2 },
new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 },
}
},

},
},
new Boss()
{
ID = 102,
Name = "Peter",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>()
{
new Person() {
ID = 102,
SID = 105,
Name = "Kaliya",
Department = "Development",
Gender = "Male",
Role = "Assistant",
PayInfo = new List<PayrollInfo>() {
new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 6 },
new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 2 },
new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 6 },
new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 8 },
new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 9 },
new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 },
}
},
new Person() {
ID = 102,
SID = 103,
Name = "Emma Watson",
Department = "Development",
Gender = "Female",
Role = "Assistant",
PayInfo = new List<PayrollInfo>() {
new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 5 },
new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 9 },
new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 },
new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 },
new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 2 },
new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 1 },
new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 },
}
}
}
}
};

BossList.Where(i => i.Employees.Any(j => j.PayInfo.Any(s => s.AbsentDays >6))).Select(m => m.Name).Dump();
}

模型类是

public class Person
{
public int ID { get; set; }
public int SID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public string Gender { get; set; }
public string Role { get; set; }
public List<PayrollInfo> PayInfo { get; set; }
}

public class Boss
{
public int ID { get; set; }
public int SID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public string Gender { get; set; }
public string Role { get; set; }
public List<Person> Employees { get; set; }
}

public class PayrollInfo
{
public int Monthof2015 { get; set; }
public int NetWorkingDays { get; set; }
public int AbsentDays { get; set; }
}

主要的 LINQ 查询是

BossList.Where(i => i.Employees
.Any(j => j.PayInfo
.Any(s => s.AbsentDays >6)))
.Select(m => m.Name);

在我的主项目中,它包含 6 个嵌套的 .Any()。由于代码冗长,这里我无法创建。

我将 EF 中的查询用作 IQueryable。数据库包含超过 1000K 条记录。

请建议我,有什么有效的方法可以最大限度地提高性能吗?

最佳答案

可能最好的方法仍然是使用 BossList 作为起点,但是构建一个 ID 列表,其中应该出现它们的 ID:

db.BossList.Where(b => db.PayrollInfos.Where(s => s.AbsentDays >6)
.Select(p => p.Employee.BossId)
.Contains(b.BossId));

在 SQL 中,这可能会转化为简洁高效的 EXISTS 查询。

请注意,我假设在您的真实模型中您有反向引用 (PayrollInfos.Employee),并且我使用了一个占位符 BossId,您应该将其替换为真正的关键属性。从你的例子中有点不清楚引用 IDSID 是如何工作的。

db 是您的 DbContext 实例。

再多解释一下这种方法:根据我的经验,通常最有效的方法是从包含您要查找的结果的集合开始查询,即 Bosslist,然后添加谓词过滤结果。其他答案以 PayrollInfo 开头。没关系,但最后您需要分组或 Distinct 来删除重复项。通常这不会使查询计划比相对简单的 WHERE EXSIST( subqyery ) 表更好。

关于c# - 如何避免在 C# LINQ 中连续嵌套 .Any,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36599076/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com