web-dev-qa-db-fra.com

LINQ, impossible de créer une valeur constante de type XXX. Seuls les types primitifs ou les types d'énumération sont pris en charge dans ce contexte.

Dans ma demande, j'ai des conférenciers et ils ont la liste des cours qu'ils peuvent enseigner et lorsque je supprime un cours, je souhaite supprimer tout lien avec les conférenciers. Voici le code:

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();
    }
}

mais ça ne marche pas. Je reçois

NotSupportedException: impossible de créer une valeur constante de type Course. Seuls les types primitifs ou les types d'énumération sont pris en charge dans ce contexte.

Qu'est-ce que je fais mal?

56
pawel1708hp

Vous ne pouvez pas utiliser Contains avec des valeurs non primitives. Faire

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

(ou le champ Id que vous utilisez).

78
Gert Arnold

Si vous utilisez un DbContext, vous pouvez interroger la collection .Local et l'opérateur == fonctionnera également avec les objets:

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();
    }
}

Le .Local est une ObservableCollection, vous pouvez donc comparer tout ce que vous voulez à l'intérieur (non limité aux requêtes SQL qui ne prennent pas en charge la comparaison d'objet). Pour vous assurer que tous vos objets appartiennent à la collection .Local, vous pouvez appeler la méthode db.Lecturers.Load () avant d'appeler .Local, qui regroupe toutes les entrées de la base de données dans la collection Local.

6
Hannish

La collection Courses de la ligne ci-dessous doit être nulle ou vide.

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

Cela peut également se produire lorsque vous passez un Func<T, bool> à Where () comme moyen d'écrire une condition dynamique comme ici ici .__ Pour une raison quelconque, le délégué ne peut pas être traduit en SQL.

0
shrutyzet

Vous ne pouvez pas comparer un type complexe si vous n'avez pas précisé ce que vous voulez dire par égalité.

Comme le dit le détail des exceptions, vous devez vérifier les valeurs primitives (comme Integer dans votre cas).

Et il vaut mieux utiliser la méthode Any() à la place.

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