Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.
Например, ниже - класс ученика, который будет использовать его в нашем коде.
public class Student {
private int id;
public int getId() {
return this.id;
}
public setId(int newId) {
this.id = newId;
}
}
Приведенный ниже код дает вам исключение с нулевым указателем.
public class School {
Student obj_Student;
public School() {
try {
obj_Student.getId();
}
catch(Exception e) {
System.out.println("Null Pointer ");
}
}
}
Поскольку вы используете Obj_Student
, но вы забыли инициализировать его, как в правильном коде, показанном ниже:
public class School {
Student obj_Student;
public School() {
try {
obj_Student = new Student();
obj_Student.setId(12);
obj_Student.getId();
}
catch(Exception e) {
System.out.println("Null Pointer ");
}
}
}
Джон и Тим уже объяснили, почему это не работает.
Предполагая, что код фильтра внутри Filter
не является тривиальным, вы можете изменить Filter
так, чтобы он возвращал выражение, которое EF может перевести .
Предположим, что у вас есть этот код:
context.Table.Where(x => x.Name.Length > 500);
Теперь вы можете создать метод, который возвращает это выражение:
Expression<Func<YourEntity, bool>> FilterByNameLength(int length)
{
return x => x.Name.Length > length;
}
Использование было бы похоже это:
context.Table.Where(FilterByNameLength(500));
Выражение, которое вы строите внутри FilterByNameLength
, может быть сколь угодно сложным, если вы можете передать его непосредственно на Where
.
Почему это работает в одном случае, а не в сумматоре?
blockquote>Поскольку EF действительно не знает о вашем методе
Filter
. Он не понимает, что он должен делать, поэтому он не знает, как перевести его в SQL. Сравните это сWhere
и т. Д., Которые он понимает .Версия, в которой вы ее называете непосредственно , работает, потому что таким образом вы не заканчивается деревом выражений, содержащим вызов
Filter
- он просто вызываетFilter
напрямую, что, в свою очередь, делает , создает запрос ... но тот, который понимает EF.Я был бы очень удивлен, если бы вы могли решить, как заставить ваш метод
Filter
работать в EF-запросе ... но вы уже сказали, что использованиеWhere
все равно работает, поэтому зачем вообще использоватьFilter
? Я бы использовал версиюWhere
- или еще лучше, используйте перегрузкуAny
, которая берет предикат:context.Table.Filter(e => e.SubTable.Any(et => et.ID < 500) && e.ID < 500);
Полезно понять разницу между Expression<Func<>>
и Func<>
.
В Expression
e => e.ID < 500
хранится информация о это выражение: есть T
e
, что вы обращаетесь к свойству ID
, вызывая оператор <
со значением int
500
. Когда EF смотрит на это, он может превратить его в нечто вроде [SomeTable].[ID] < 500
.
A Func
e => e.ID < 500
- это метод, эквивалентный:
static bool MyMethod(T e) { return e.ID < 500; }
Он скомпилирован как IL-код, который делает это; он не предназначен для «восстановления» SQL-запроса или чего-то еще, только запускается.
Когда EF принимает ваш Expression
, он должен понимать каждую его часть, потому что он использует это для построения SQL запрос. Он запрограммирован на то, что означает существующий метод Where
. Он не знает, что означает ваш метод Filter
, хотя это тривиальный метод, поэтому он просто уходит.
Where
, потому что каждое выражение, которое вы передаете самому внешнемуWhere
, фактически не выполняется, а интерпретируется. – Daniel Hilgarth 20 August 2013 в 16:34