LINQ, Невозможно создать постоянное значение типа XXX. В этом контексте поддерживаются только примитивные типы или типы перечислений

В моем приложении у меня есть Лекторы, и у них есть список курсов, которые они могут преподавать, и когда я удаляю курс, я хочу удалить соединение с преподавателями. Здесь код:

public void RemoveCourse(int courseId)
{
    using (var db = new AcademicTimetableDbContext())
    {
        var courseFromDb = db.Courses.Find(courseId);

        var toRemove = db.Lecturers
                        .Where(l => l.Courses.Contains(courseFromDb)).ToList();

        foreach (var lecturer in toRemove)
        {
            lecturer.Courses.Remove(courseFromDb);
        }

        db.SaveChanges();
    }
}

но это не сработает. Я получаю

NotSupportedException: невозможно создать постоянное значение типа Course. В этом контексте поддерживаются только примитивные типы или типы перечислений.

Что я делаю неправильно?

Ответ 1

Вы не можете использовать Contains с не-примитивными значениями. У

Where(l => l.Courses.Select(c => c.CourseId).Contains(courseId)

(или используемое поле Id).

Ответ 2

Если вы используете DbContext, вы можете запросить коллекцию .Local, а оператор == будет работать и с объектами:

public void RemoveCourse(int courseId)
{
    using (var db = new AcademicTimetableDbContext())
    {
        var courseFromDb = db.Courses.Find(courseId);

        db.Lecturers.Load() //this is optional, it may take some time in the first load

        //Add .Local to this line
        var toRemove = db.Lecturers.Local 
                        .Where(l => l.Courses.Contains(courseFromDb)).ToList();

        foreach (var lecturer in toRemove)
        {
            lecturer.Courses.Remove(courseFromDb);
        }

        db.SaveChanges();
    }
}

.Local - это ObservableCollection, поэтому вы можете сравнивать все, что вам нравится внутри (не ограничиваясь SQL-запросами, которые не поддерживают сравнение объектов). Чтобы убедиться, что вы все объекты в коллекции .Local, вы можете вызвать метод db.Lecturers.Load() перед вызовом .Local, который приводит все записи базы данных в локальную коллекцию.

Ответ 3

Коллекция Courses ниже строки должна быть пустой или пустой.

 var toRemove = db.Lecturers
                        .Where(l => l.Courses.Contains(courseFromDb)).ToList();

Ответ 4

Это также может произойти, когда вы передаете Func<T, bool> в Where() как способ записи динамического условия, например здесь здесь По какой-то причине делегат не может быть переведен в SQL.

Ответ 5

Вы не можете сравнивать сложный тип, если вы не указали, что вы подразумеваете под равенством.

Как говорится в деталях исключения, вам нужно проверить примитивные значения (например, Integer в вашем случае).

И лучше вместо этого использовать метод Any().

var toRemove = db.Lecturers
     .Where(l => l.Courses.Any(p=>p.Id == courseFromDb.Id)).ToList();