【问题标题】:LINQ, Unable to create a constant value of type XXX. Only primitive types or enumeration types are supported in this contextLINQ,无法创建 XXX 类型的常量值。此上下文仅支持原始类型或枚举类型
【发布时间】:2012-11-15 20:24:10
【问题描述】:

在我的应用程序中,我有讲师,他们有他们可以教授的课程列表,当我删除课程时,我想删除与讲师的连接。代码如下:

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 类型的常量值。此上下文仅支持原始类型或枚举类型。

我做错了什么?

【问题讨论】:

标签: c# entity-framework linq


【解决方案1】:

您不能将Contains 与非原始值一起使用。做

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

(或您使用的 Id 字段)。

【讨论】:

  • 很好的答案@gert-arnold !我在这里收到了同样的错误消息,但我使用的是 Join 和计算值,而不是 contains 方法。在这种情况下,我只需要在执行连接之前枚举上下文结果。
【解决方案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 集合中获得所有对象,您可以在调用 .Local 之前调用 db.Lecturers.Load() 方法,这会将所有数据库条目都带入 Local 集合中。

【讨论】:

    【解决方案3】:

    下一行的Courses 集合应为空或为空。

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

    【讨论】:

      【解决方案4】:

      当您将 Func<T, bool> 传递给 Where() 作为编写动态条件的一种方式时,也会发生这种情况,例如此处 here 由于某种原因,委托无法转换为 SQL。

      【讨论】:

        【解决方案5】:

        如果您没有指定相等的含义,则无法比较复杂类型。

        正如异常细节所说,您需要检查原始值(如您的情况下的整数)。

        最好改用Any() 方法。

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

        【讨论】:

          猜你喜欢
          • 2015-08-26
          • 1970-01-01
          • 2013-09-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多