问题描述
我有一个linq查询,该查询从sql Server数据库中获取记录。例如,电话号码存储为字符串,并且可以包含在搜索时找不到的空格或字符。
即我搜索电话号码“ 0123456789”,但在数据库中将其存储为“ 01234 567890”或“ 01234-567890”等。在下面的代码中,您可以看到我试图去除字符(对还是错!)的尝试,但是我除非我在空格“ 567890”之后搜索字符,否则仍然不会获得任何结果。
使用以下代码:
“ 567890”返回正确的结果
“ 01202 567890”没有返回结果
“ 01202567890”未返回任何结果
Expression<Func<Customer,bool>> SearchVals = ContainsInDescription("01234567890");
var query = (from customer in data.Customers.Where(SearchVals)
where customer.Deleted == false
orderby customer.Name ascending
select new
{
CustomerID = customer.CustomerID.ToString(),Name = customer.Name,Company = customer.Company,Home = customer.PhoneHome.Replace(" ",""),Mobile = customer.PhoneMobile.Replace(" ",Work = customer.PhoneWork.Replace(" ",Email = customer.Email,Address1 = customer.Address.AddressLine1,Address2 = customer.Address.AddressLine2,City = customer.Address.City,County = customer.Address.County,Postcode = customer.Address.PostalCode,Country = customer.Address.Country
}).Skip(totalTodisplay * page).Take(totalTodisplay);
public Expression<Func<Customer,bool>> ContainsInDescription(
params string[] keywords)
{
Expression<Func<Customer,bool>> predicate = PredicateBuilder.False<Customer>();
foreach (string keyword in keywords)
{
string temp = keyword;
//string predicate1 = PhoneHome.ToString().Replace(" ","").Replace("-","").Replace("(","").Replace(")","").Trim();
string predicate2 = temp.ToString().Replace(" ","").Trim();
predicate = predicate.Or(p => p.Name.Contains(temp));
predicate = predicate.Or(p => p.Company.Contains(temp));
predicate = predicate.Or(p => p.PhoneHome.Contains(temp));
predicate = predicate.Or(p => p.PhoneMobile.Contains(temp));
predicate = predicate.Or(p => p.PhoneWork.Contains(temp));
//predicate = predicate.Or(p => p.PhoneHome.ToString().Replace(" ","").Contains(temp.ToString().Replace(" ","")));
//predicate = predicate.Or(p => p.PhoneMobile.ToString().Replace(" ","")));
//predicate = predicate.Or(p => p.PhoneWork.ToString().Replace(" ","")));
//predicate = predicate.Or(p => p.PhoneHome.ToString().Replace(" ","").Trim() == temp.ToString().Replace(" ","").Trim());
//predicate = predicate.Or(p => p.PhoneMobile.ToString().Replace(" ","").Trim());
//predicate = predicate.Or(p => p.PhoneWork.ToString().Replace(" ","").Trim());
predicate = predicate.Or(p => p.Email.Contains(temp));
predicate = predicate.Or(p => p.Address.AddressLine1.Contains(temp));
predicate = predicate.Or(p => p.Address.AddressLine2.Contains(temp));
predicate = predicate.Or(p => p.Address.City.Contains(temp));
predicate = predicate.Or(p => p.Address.County.Contains(temp));
predicate = predicate.Or(p => p.Address.PostalCode.Contains(temp));
predicate = predicate.Or(p => p.Address.Country.Contains(temp));
}
return predicate;
}
解决方法
您可能还需要清除从数据库收集的数据。当前,您仅删除空格。与其使用大量白名单方法,不如替换很多东西:
using System;
using System.Linq;
using System.Text;
public static void Main()
{
Func<string,String> onlyNumbers = data
=> data.Where(c => char.IsDigit(c)) // only keep digits
.Aggregate(new StringBuilder(),(builder,c) => builder.Append(c))
.ToString(); // gimme concatted string
Console.WriteLine(onlyNumbers( "sadf(234)-23492sas" )); // => "23423492"
}
在“更清洁”上方使用类似
...
Mobile = onlyNumbers(customer.PhoneMobile),Home = onlyNumbers(customer.PhoneHome),Mobile = onlyNumbers(customer.PhoneMobile),Work = onlyNumbers(customer.PhoneWork),...
和
pred = pred.Or(p => p.Mobile.Contains(onlyNumbers(_some_input_)));
应该可以解决问题。
您可以定义自己的允许字符(或也允许'+')的哈希集,而不是char.IsDigit()
来允许f国际预拨号码为+41 1234 5678 90
注意-这会从任何文本中产生数字,可能会给您带来假阳性:
onlyNumbers("This 246 cars had 102 violations of rule 47.11 in the year 2012");
为您提供一串"24610247112012"
。