如何在C#LINQ中构建高效的查询来过滤数据

时间:2016-04-13 09:37:20

标签: c# linq

我有一个集合List<Person> Members。我需要根据一些标准过滤列表。

请参考以下C#代码:

void Main()
{
    List<Person> Members = new List<Person>()
    {
        new Person() { ID = 101, Name = "Harry", Department = "Testing", Gender = "Male", Role = "Manager"},
        new Person() { ID = 102, Name = "Peter", Department = "Development", Gender = "Male", Role = "Manager"},
        new Person() { ID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
        new Person() { ID = 104, Name = "Raj", Department = "Development", Gender = "Male", Role = "Manager"},
        new Person() { ID = 105, Name = "Kaliya", Department = "Testing", Gender = "Male", Role = "Assistant"},
    };
}

模型类是:

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Department { get; set; }
    public string Gender { get; set; }
    public string Role { get; set; }
}

现在考虑一下情景

场景#1 :使用ID搜索

List<KeyValuePair<string, string>> searchCriteria = new List<System.Collections.Generic.KeyValuePair<string, string>>()
    {
        new KeyValuePair<string, string>("ID", "102")
    };

场景#2 :使用ID&amp;搜索系

List<KeyValuePair<string, string>> searchCriteria = new List<System.Collections.Generic.KeyValuePair<string, string>>()
    {
        new KeyValuePair<string, string>("ID", "101"),
        new KeyValuePair<string, string>("DEP", "Testing")
    };

场景#3 :使用部门,性别和角色进行搜索

List<KeyValuePair<string, string>> searchCriteria = new List<System.Collections.Generic.KeyValuePair<string, string>>()
{
    new KeyValuePair<string, string>("DEP", "Development"),
    new KeyValuePair<string, string>("Gender", "Male"),
    new KeyValuePair<string, string>("Role", "Manager"),
};

搜索查询应该像

var iQuery = Members.AsQueryable();

foreach (var item in searchCriteria)
{
    switch (item.Key)
    {
        case "ID":
            iQuery = iQuery.Where(p => p.ID == int.Parse(item.Value));
            break;

        case "Name":
            iQuery = iQuery.Where(p => p.Name.Contains(item.Value));
            break;

        case "DEP":
            iQuery = iQuery.Where(p => p.Department == item.Value);
            break;

        case "Gender":
            iQuery = iQuery.Where(p => p.Gender == item.Value);
            break;

        case "Role":
            iQuery = iQuery.Where(p => p.Role == item.Value);
            break;
    }
}

在我的真实项目中,我在数据库中有超过1000K的记录。而不是

var iQuery = Members.AsQueryable();

我正在使用

var iQuery = db.Members.AsQueryable();

查询数据需要20到25秒。请帮助我如何在C#LINQ中构建更有效的查询来过滤数据。

2 个答案:

答案 0 :(得分:2)

这里的问题不在于LINQ实际在做什么。方案2的查询只会创建类似的内容:

SELECT * FROM
PERSON
WHERE Department = N'Development'
AND Gender = N'Male'
AND Role = N'Manager'

您需要直接针对数据库运行此操作,以确定您的性能瓶颈是什么。您很可能缺少索引,因此强制数据库服务器扫描整个表以获取结果集。

如果您正在使用SQL Server,请尝试运行探查器以确定(假设)LINQ-to-EF正在生成并调整它的确切查询。

答案 1 :(得分:-2)

您需要优化数据库,查看索引

您也可以使用Specification pattern

执行相同的请求
    public class NamedPersonSpecification : AbstractSpecification<Person>
{
    private string _name;
    public NamedPersonSpecification(string name)
    {
        this._name= name;
    }

    public override bool IsSatisfiedBy(Person o)
    {
        return o.Name.Equals(_name);
    }
}

并像这样查询:

IQueryable<T>.Where(specification.IsSatisfiedBy)

优点是要更清楚地请求您的LINQ