我有一个Collection List 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的记录。
请建议我,是否有任何有效的方法可以最大限度地提高性能?
答案 0 :(得分:2)
执行此操作的最佳方法可能仍然是使用BossList
作为起点,但要构建一个Ids列表,其中应显示其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
,您应该用实际的键属性替换它。从您的示例中可以清楚地了解引用ID
和SID
的工作原理。
db
是您的DbContext
个实例。
更多地解释这种方法:根据我的经验,通常最好使用包含您所追求的结果的集合(即Bosslist
)开始查询,然后添加过滤结果的谓词。其他答案以PayrollInfo
开头。没关系,但最后你需要分组或Distinct
删除重复项。通常,这不会使查询计划优于相对简单的table WHERE EXSIST( subqyery )
。
答案 1 :(得分:1)
如果您将“外键”等内容添加到“父母”中,该怎么办?在每个实体?
public class PayrollInfo
{
public int Monthof2015 { get; set; }
public int NetWorkingDays { get; set; }
public int AbsentDays { get; set; }
public Person Person { get; set; }
}
当您在构造函数中创建Person
- 参数时可以设置新属性:
public Person(IList<PayrollInfo> list)
{
this.PayInfo = list;
foreach(var pay in this.PayInfo)
pay.Person = this;
}
或者只定义一个设置PayInfo
的方法。随你喜欢。
然后为Person和Boss做同样的事情。
然后你可以像
AllPayrollInfos.Where(x => x.Days > 6).GroupBy(x => x.Person.Boss).Select(x => x.Key).ToList();
答案 2 :(得分:1)
假设这是一个淡化的EF查询;我会将您的选择反转为以PayrollInfo开头,然后选择Boss名称:
Boss Boss = new Boss
{
ID = 101,
Name = "Harry",
Department = "Development",
Gender = "Male",
Role = "Manager",
};
Person Person = new Person() { ID = 101, SID = 102, Name = "Peter", Department = "Development", Gender = "Male", Role = "Assistant", Boss = Boss};
List<PayrollInfo> PayrollInfoList = new List<UserQuery.PayrollInfo>
{
new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 6, Person = Person },
new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3, Person = Person },
new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 2, Person = Person },
new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 1, Person = Person },
new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 4, Person = Person },
new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 6, Person = Person },
new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4, Person = Person },
new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3, Person = Person },
new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 8, Person = Person },
new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 9, Person = Person },
new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 4, Person = Person },
new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1, Person = Person },
};
PayrollInfoList.Where(p => p.AbsentDays > 6).Select(p => p.Person.Boss.Name).Distinct().Dump();