2015-04-16 9 views
0

Я пытаюсь найти способ создания предложения where и передать его методу Get() репозитория. Он должен фильтровать элементы, имя которых начинается с определенной буквы. Я смог построить часть этого тела Where Where, но не могу найти способ обработки сценария, когда имя элемента не начинается с буквы. Например: _ItemName или 97_SomeName.Build where clause body

Итак, вот мой метод:

protected override Expression<Func<DataSetSettings, bool>> GetWhereClause() 
{ 
    //The user has selected FilterLetter, for example: "A" 
    // return all items which name starts with "A" 
    if (!string.IsNullOrWhiteSpace(FilterLetter) && !FilterLetter.Equals("All")) 
     return (x => x.Name.StartsWith(FilterLetter) && x.Type == Type); 

    if (FilterLetter.Equals("Other")) 
    { 
     //Here i need to extract all items which name does not start with letter 
    } 

    //return All items of the current type 
    return x => x.Type == Type; 
} 

Я был бы признателен за любую помощь! Благодаря!

+0

Вы используете Linq для SQL или Entity Framework или это для коллекций памяти? – jwatts1980

+0

Я использую Entity Framework. – vortex

+0

Вы попробовали что-то первое и получили сообщение об ошибке? Я не думаю, что у Entity есть эквивалент «StartsWith». – jwatts1980

ответ

1

Теперь, когда я понимаю, что вам нужно, я огляделся и не смог найти изящное решение этого. Похоже, что сложное сопоставление строковых строк является слабым местом в EF.

Единственный способ, которым я могу видеть, чтобы сделать это, либо сравнивать с каждой буквы, а именно:

!x.Name.StartsWith("A") && !x.Name.StartsWith("B") && //on and on to Z 

Или чтобы убедиться, что весь список загружается в память, а затем использовать регулярные выражения для фильтрации:

protected override Expression<Func<DataSetSettings, bool>> GetWhereClause() 
{ 
    var noletter = new Regex("^[^a-z].*", RegexOptions.IgnoreCase); 

    return (
     x => x.Type == Type && (
      string.IsNullOrWhiteSpace(FilterLetter) || 
      FilterLetter == "All" || 
      (FilterType == "Other" && noletter.IsMatch(x.Name)) || 
      x.Name.StartsWith(FilterType) 
     ) 
    ); 
} 

Если вы в конечном итоге собираетесь с возможностью загрузки всего в память, вы можете, по крайней мере, сначала фильтровать на основе x.Type. Это, по-видимому, общий знаменатель в фильтрации. По крайней мере, вам не нужно загружать всю таблицу в память.

+0

Спасибо за ответ. У меня уже есть работа с фильтрацией коллекции в памяти. Я надеялся найти способ сделать это на уровне базы данных. – vortex

+0

@vortex SQL Server поддерживает регулярные выражения, но для Entity Framework и Linq to SQL нет переводов для них.Лучшее, что вы можете сделать, это имитировать оператор 'LIKE', который является тем, что использует' Contains' и 'StartsWith' под капотом. – jwatts1980

+0

пока я использую ваше решение с регулярным выражением. Еще раз спасибо. – vortex

1

можно сделать равным ложна на вашем StartsWith

Как это:

return (x => x.Name.StartsWith(FilterLetter) == false && x.Type == Type);

+2

Или '! X.Name.StartsWith (FilterLetter) &&' ... – jwatts1980

+0

Это не сработает. Если пользователь выбирает «Другое» для фильтрации, тогда мне нужно привести все элементы, имя которых не начинается с буквы. Пример: '_Asd, 12Name, * 1OtherName' – vortex

+0

@vortex вы говорите« письмо », но ваши примеры являются строками. Является ли это одним символом или несколькими символами, которые не могут быть в начале значения? – jwatts1980

0

Мой совет должен был бы сделать 1 дб вызов всех типов в списке, а затем использовать LINQ для запроса этот список , Ваш пример будет делать два вызова db.

List<Type> allTypes = new List<Type>(); 
List<Type> typesWithA = new List<Type>(); 
List<Type> typesWOA = new List<Type>(); 

// make one db call 
allTypes = entities.Types.ToList(); 

typesWithA = allTypes.Where(x => x.Name.StartsWith(FilterLetter)).ToList(); 
typesWOA = allTypes.Where(x => !x.Name.StartsWith(FilterLetter)).ToList(); 
+0

Это может быть значительное повышение производительности, если' Types' является большой таблицей. – jwatts1980

+0

Правда. Ему нужно было найти другой фильтр, чтобы он не вытащил тонны рядов. – fischgeek