Выполнение запроса LINQ с необязательными условиями поиска - PullRequest
0 голосов
/ 16 июля 2010

У меня есть страница, где вы можете искать людей. Они могут либо получить список всех людей, либо отфильтровать его по определенным критериям, таким как имя или фамилия.

До сих пор я пытался использовать технику, описанную в этом вопросе .

Так что мой код выглядит как

string firstname=...
string lastname=...

var people=from p in People.All()
           where (firstname==null || firstname.ToLower()==p.FirstName.ToLower()) &&
                 (lastname==null || lastname.ToLower()==p.LastName.ToLower())
           select p;

Я получаю ошибку нулевой ссылки при построении запроса, однако, когда и имя, и фамилия равны нулю. Удаление предложения where избавляет от ошибки.

Почему бы это не сработало? C # пытается оценить вторую часть каждой части предложения where? Это не должно быть из-за короткого замыкания или верно?

Ответы [ 4 ]

1 голос
/ 17 июля 2010

Использовать string.Equals:

from p in People.All()
where (firstname == null || string.Equals (firstname, p.FirstName, StringComparison.InvariantCultureIgnoreCase)) &&
      (lastname == null || string.Equals (lastname, p.LastName, StringComparison.InvariantCultureIgnoreCase))
select p

Это не только позволяет избежать проблемы с нулем, но и вынуждает вас указать тип сравнения строк (это хорошо).Другими словами, вы указываете, использовать ли правила, специфичные для локальной или инвариантной культуры, при выполнении сравнения без учета регистра.

1 голос
/ 16 июля 2010

вам не нужно звонить ToLower() вместо этого используйте string.compare с ignoreCase

string.Compare(firstName, p.FirstName, true) 
0 голосов
/ 16 июля 2010

Не работает, когда оба значения равны нулю, потому что первая часть выражения будет иметь значение true, что не позволит закорочить оценку Почему бы не использовать правила эквивалентности, чтобы перевернуть утверждение?

(firstName != null && firstName.ToLower() == p.firstName.ToLower()) 

РЕДАКТИРОВАТЬ: я написал следующее и успешно запустил его в LINQPad 4, без проблем. Я предполагаю, что вызов People.All() просто возвращает IQueryable<People> с полным набором записей? Может быть, опубликуете здесь текст вашего исключения, чтобы мы могли увидеть, если вы что-то случайно пропустили?

void Main()
{
    string a = null;
    string b = null;
    var peeps = new List<Person> { 
        new Person { 
            FirstName = "John",
            LastName = "Connor"
        },
        new Person { 
            FirstName = "Sarah",
            LastName = "Connor",
        },
        new Person { 
            FirstName = "Cletus",
            LastName = "Handy"
        }
    };

    var somePeeps = from p in peeps
        where (a == null || a.ToLower() == p.FirstName.ToLower()) 
            && (b == null || b.ToLower() == p.LastName.ToLower())
        select p;

    somePeeps.Dump();

}

public class Person
{
    public string FirstName { get; set;}
    public string LastName { get; set;}
}
0 голосов
/ 16 июля 2010

Перед вызовом ToLower убедитесь, что он не равен нулю:

(firstname==null || (firstname!= null && firstname.ToLower()==p.FirstName.ToLower()))
...