Я бы создал приватную структуру:
private struct UnpackedAndPacked
{
public string Unpacked {get;set;}
public string Packed {get;set;}
}
var ws = from w in query.Split()
where !String.IsNullOrWhiteSpace(w)
select new UnpackedAndPacked
{
Unpacked=w,
Packed=PhoneNumber.Pack(w)
};
Затем изменил бы условие:
where ws.All(w =>
c.FirstName == w.Unpacked
|| c.LastName == w.Unpacked
|| c.EmailAddress == w.Unpacked
|| c.HomePhone == w.Packed
|| c.CellPhone == w.Packed)
select c;
Я изучил это дальше, и я думаю, что вы несобирается сделать это как есть.Проблема в том, что из-за ws.All
он хочет создать набор SQL-предложений один раз для каждого значения в последовательности ws
.Это должно быть последовательность примитивных типов, например строка.
Если бы вы могли изменить свой код так, чтобы он имел два параметра запроса, то я думаю, что это может сработать.Вам понадобится один набор параметров для вещей, которые не нуждаются в упаковке, и один для тех, которые делают.Затем вы измените это в цепочку методов LINQ и сделаете союз между ними.Пример для подражания.
Это сработало.Мой код ниже.Обратите внимание, что я использовал базу данных AdventureWorks2008R2, поэтому у меня она немного сложнее, чем у вас - у меня есть коллекция адресов электронной почты и телефонов для работы;принимается совпадение по любому из них:
public static IQueryable<Person> SearchCustomers(
AdventureWorksEntities entities, string nameQuery, string phoneQuery)
{
var wsu = from w in nameQuery.Split()
where !String.IsNullOrWhiteSpace(w)
select w;
var wsp = from w in phoneQuery.Split()
where !String.IsNullOrWhiteSpace(w)
select Pack(w);
return
entities.People.Where(
c => wsu.All(w => c.FirstName == w || c.LastName == w)).
Union(
entities.People.Where(
c =>
wsp.All(
w =>
c.PersonPhones.Any(p => p.PhoneNumber == w) ||
c.EmailAddresses.Any(a => a.EmailAddress1 == w))));
}
Обратите также внимание, что я нашел другой способ получения трассировки :
IQueryable<Person> query = SearchCustomers(entities, "w1 w2",
"(602) (408)");
var oc = (ObjectQuery<Person>) query;
Console.WriteLine(oc.ToTraceString());