在连接列中搜索的方法是什么?

时间:2017-05-02 03:29:04

标签: c# sql entity-framework linq

假设我有一个这样的课程:

class Person
{
   string FirstName;
   string MiddleName;
   string LastName;
}

假设我有这样的样本数据:

William Henry  Gates
Steven  Paul   Jobs 
Mark    Elliot Zuckerberg

然后,在Entity Framework / Linq中,我可以进行如下搜索:

string search = "paul";

search = search.ToUpper();
var people = db.People
    .Where(p => p.FirstName.ToUpper().Contains(search)
    .Where(p => p.MiddleName.ToUpper().Contains(search)
    .Where(p => p.LastName.ToUpper().Contains(search);

这很有效。但是,如果用户搜索,例如:

search = "Henry Gates";

糟糕..理论上,(1)必须有效:

    .Where(p => (p.FirstName +" "+ p.MiddleName +" "+ p.LastName).ToUpper().Contains(search);

(2)必须有效:

    .Where(p => (p.FirstName.ToUpper() +" "+ p.MiddleName.ToUpper() +" "+ p.LastName.ToUpper()).Contains(search);

并且有一个选项(3)我能想到:

.Select(p => new {FullName = p.FirstName +" "+ p.MiddleName +" "+ p.LastName)} )
.Where(p => p.FullName.Contains(search) )

最后,我的问题。在小表中,这不是那么相关,但在大表(如500k记录)中,它可能是一个问题,因为(在我的示例中)FirstName,MiddleName和LastName是索引字段,并且在每个字段中单独搜索很好,但是连接查询中的字段,SQL将执行全表扫描而不是使用索引,这使得简单的查询变得非常缓慢。

使用EntityFramework / Linq更复杂,因为我不确切知道将用于连接我的字段的标准是什么。

那么在连续列中搜索的方式是什么?

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

如果位置不相关,您可以先将输入字符串分解为List,然后使用contains查找匹配结果

// Define the search string
List<string> searchInput = new List<string> { "Paul", "Henry Gates", "Gates Henry" };

// Define the data
List<Person> persons = new List<Person>();
persons.Add(new Person() { FirstName = "William", MiddleName = "Henry", LastName = "Gates" });
persons.Add(new Person() { FirstName = "Steven", MiddleName = "Paul", LastName = "Jobs" });
persons.Add(new Person() { FirstName = "Mark", MiddleName = "Elliot", LastName = "Zuckerberg" });

// It may problem if you want to specific the field in sequence
persons.Add(new Person() { FirstName = "Henry", MiddleName = "Elliot", LastName = "Gates" });
// Another problem if a field contains all values
persons.Add(new Person() { FirstName = "Henry Gates", MiddleName = "Elliot", LastName = "Gates" });

// find the person
foreach (string input in searchInput)
{
    List<string> inputList = input.Split(' ').Select(s => s.ToUpperInvariant()).ToList();
    var qry = persons.Where(p => inputList.Contains(p.FirstName.ToUpperInvariant()) ||
                                    inputList.Contains(p.MiddleName.ToUpperInvariant()) ||
                                    inputList.Contains(p.LastName.ToUpperInvariant()));
    var results = qry.ToList();
    Console.WriteLine(string.Format("Search: {0} Found: {1}", input, results.Count));
    foreach(var p in results)
    {
        Console.WriteLine(p.ToString());
    }
    Console.WriteLine();
}

结果如下:

Search: Paul Found: 1
First Name: Steven; Middle Name: Paul; Last Name: Jobs

Search: Henry Gates Found: 3
First Name: William; Middle Name: Henry; Last Name: Gates
First Name: Henry; Middle Name: Elliot; Last Name: Gates
First Name: Henry Gates; Middle Name: Elliot; Last Name: Gates

Search: Gates Henry Found: 3
First Name: William; Middle Name: Henry; Last Name: Gates
First Name: Henry; Middle Name: Elliot; Last Name: Gates
First Name: Henry Gates; Middle Name: Elliot; Last Name: Gates

希望这符合您的目的

小提琴:http://rextester.com/XFXBEQ27713