Entity Framework не отправляет предложение WHERE в базу данных SQL Server [дубликат]

Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.

Например, ниже - класс ученика, который будет использовать его в нашем коде.

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 ");
        }
    }
}
14
задан Pedro.The.Kid 31 March 2014 в 16:32
поделиться

3 ответа

Джон и Тим уже объяснили, почему это не работает.

Предполагая, что код фильтра внутри 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.

21
ответ дан Daniel Hilgarth 20 August 2018 в 07:34
поделиться
  • 1
    по большому количеству чтений и проб и ошибок, я подозревал, что это единственный способ. будут ли работать такие случаи, как context.Table.Where (e = & gt; e.subTable.Any (MyFilter ())); – Pedro.The.Kid 20 August 2013 в 16:32
  • 2
    @ Pedro.The.Kid: Нет, не будет. Результат этого метода необходимо передать самому внешнему Where, потому что каждое выражение, которое вы передаете самому внешнему Where, фактически не выполняется, а интерпретируется. – Daniel Hilgarth 20 August 2013 в 16:34
  • 3
    Я сделал тест, и это работает var filter = MyFilter (); context.Table.Where (e = & gt; e.subTable.AsQueryable (). Любой (фильтр)); – Pedro.The.Kid 20 August 2013 в 17:16
  • 4
    @Pedro: Интересно. EF, кажется, оценивает его, потому что из POV выражения это константа. Хорошая находка. – Daniel Hilgarth 20 August 2013 в 17:19

Почему это работает в одном случае, а не в сумматоре?

Поскольку 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);
5
ответ дан Jon Skeet 20 August 2018 в 07:34
поделиться
  • 1
    есть ли способ, которым он может быть изменен, чтобы в конечном итоге с одним деревом выражений доза ведьмы не включала имя метода? – Pedro.The.Kid 20 August 2013 в 15:40
  • 2
    @ Pedro.The.Kid: Не легко. Вы можете написать метод, который переписал дерево выражений и создал на его основе новый запрос, но неясно, почему вы хотите это сделать, и это было бы сложно. – Jon Skeet 20 August 2013 в 15:41
  • 3
    что касается использования там, где его просто для легкой проверки в реальной среде, это будет намного сложнее. – Pedro.The.Kid 20 August 2013 в 15:47
  • 4
    @ Pedro.The.Kid: Ну, не зная, что вы на самом деле пытаетесь достичь, вам сложно помочь, но в основном вам будет трудно сделать что-то подобное. – Jon Skeet 20 August 2013 в 16:01
  • 5
    – Johni Michels 27 August 2018 в 11:59

Полезно понять разницу между 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, хотя это тривиальный метод, поэтому он просто уходит.

7
ответ дан Tim S. 20 August 2018 в 07:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: