Мне нужно сравнить номера телефонов в Linq с объектами. Я использую Regex, чтобы я мог сравнивать только числа при игнорировании формата.
Поскольку мы не можем использовать предложение Regex в where, чтобы получить список телефонных номеров, а затем применить цикл для сравнения номеров телефонов.
Вот код:
/// <summary>
/// Check Phone number exist or Not
/// </summary>
/// <param name="accountNumber"></param>
/// <returns></returns>
public bool CheckPhoneNumberExist(string phoneNumber)
{
LP= new LPEntities();
// In order to compare phone number, we need to use regex so that we can compare only numbers and not any specific format
phoneNumber = Regex.Replace(phoneNumber, "[^0-9]", "");
var phoneList = (from act in LP.Accounts
select act).ToList();
if (phoneList.Count > 0)
{
foreach (var item in phoneList)
{
if (item.Telephone != null)
{
if (Regex.Replace(item.Telephone, "[^0-9]", "") == phoneNumber)
{
return true;
}
}
}
}
return false;
}
Код работает нормально, но есть проблема с производительностью. У нас есть 20 тысяч записей в базе данных, которые продолжают расти, поэтому медленнее создавать список, а затем перебирать этот список.
Как мы можем оптимизировать вышеуказанное? Есть ли какое-то другое решение, например, если мы можем сделать это с помощью хранимой процедуры?
Благодаря,
Обратите внимание, что ваша техника регулярных выражений не будет определять, что эти числа на самом деле одинаковы:
+441234567890
+44 (0)1234 567890
01234 567890
Мой первый выбор состоял в том, чтобы сохранить номер как varchar без форматирования и только форматировать его для отображения. Это означает, что вы избавитесь от регулярного выражения при поиске, и вы можете добавить индекс, чтобы ускорить его еще больше.
Моим вторым выбором было бы добавить столбец, чтобы вы сохранили оба и синхронизировали их.
См. Ответы здесь:
Лучше ли хранить номера телефонов в каком-то каноническом формате или "как указано"?
Наконец, вы можете получить некоторое улучшение, если вы измените свой linq на это:
bool exists = (from act in LP.Accounts
where act.Telephone != null //move the null check to the database
select act.Telephone) //select only the telephone number
.AsEnumerable() //using linq-to-objects
//after retrieving the results from the database
//lets you use Regex
//- but it does get them all into memory
.Any(pn => Regex.Replace(pn, "[^0-9]", "") == phoneNumber)
//Any stops at the first one
//better than Counting them all then checking '> 0'
Как в сторону. Добавление проверки, if (phoneList.Count > 0)
избыточно перед foreach (var item in phoneList)
потому что тело цикла не выполняется, если в списке нет элементов.
Я пробовал один новый подход, когда я заменяю символы дополнительного формата на "", как указано ниже
select account, telephone from account where
Replace(Replace(Replace(Replace(Replace(telephone, '-',''), '(',''),')',''),' ',''),'+',''
)='9084336325'
но он будет работать только тогда, когда мы будем понятны для замены других символов.
Во-первых, вы загружаете весь список сущностей, которые вы выполняете с двумя регулярными выражениями для каждой проверки. Что-то вроде этого должно быть более эффективным:
public bool CheckPhoneNumberExist(string newPhoneNumber)
{
LP = new LPEntities();
var phoneList = (from act in LP.Accounts
select act).ToList();
foreach (string phoneNumber in phoneList)
Add(phoneNumber);
return Add(newPhoneNumber);
}
private HashSet<string> _uniquePhoneNumbers = new HashSet<string>();
public bool Add(string phoneNumber)
{
// Only use Regex if necessary
if (!IsNumeric(phoneNumber))
phoneNumber = RemoveNonNumericCharacters(phoneNumber);
// Returns false if string already exists in HashSet
return !_uniquePhoneNumbers.Add(phoneNumber);
}
private static readonly char[] _forbiddenChars = new char[] { ',', '.', '.', ' ', '+', '-' };
private static bool IsNumeric(string s)
{
foreach(char c in _forbiddenChars)
if(s.IndexOf(c) >= 0)
return false;
return true;
}
private static string RemoveNonNumericCharacters(string s)
{
return Regex.Replace(s, "[^0-9]", "");
}
Другой подход заключается в том, чтобы убедиться, что номера сохраняются в стандартизованном формате с самого начала.