C# 为什么我的ASP.NET MVC 4应用程序创建新实体而不是更新旧实体?

C# 为什么我的ASP.NET MVC 4应用程序创建新实体而不是更新旧实体?,c#,asp.net,asp.net-mvc,entity-framework,asp.net-mvc-4,C#,Asp.net,Asp.net Mvc,Entity Framework,Asp.net Mvc 4,编辑:我选择的解决方案可能不是最好的,但确实有效。我将在下周检查我的代码(一旦这个项目完成),当我了解到哪里出了问题时,我会更新我的问题 我将ASP.NETMVC4框架与Entity5一起使用。下面是一些代码: 要在数据库中实例化和保存(刷新)的类: public class ClassCancellation { [Key] public int Id { get; set; } public Faculty Professor

编辑:我选择的解决方案可能不是最好的,但确实有效。我将在下周检查我的代码(一旦这个项目完成),当我了解到哪里出了问题时,我会更新我的问题

我将ASP.NETMVC4框架与Entity5一起使用。下面是一些代码:

要在数据库中实例化和保存(刷新)的类:

    public class ClassCancellation
    {
        [Key]
        public int Id { get; set; }
        public Faculty Professor { get; set; }
        public DateTime CancelledOn { get; set; }
        public Course Course { get; set; }
        [Required]
        public ClassDate ClassCancelled { get; set; }
        public Message CancellationMessage { get; set; }
        [Required]
        public List<Student> Students { get; set; }
    }
这是一种回购方法,它将
CancellationFull
转换为
ClassCancellation
,然后将其保存到数据库:

    public CancellationFull createClassCancellation(CancellationFull c) 
    {
        ClassCancellation newCancellation = Mapper.Map<ClassCancellation>(c);

        dc.ClassCancellations.Add(newCancellation);
        dc.SaveChanges();

        return Mapper.Map<CancellationFull>(dc.ClassCancellations.FirstOrDefault(cc => cc.Id == newCancellation.Id));
    }
以下是其中一种回购方法的示例(其他方法非常类似):

public CourseForList getForList(int?id)
{
返回Mapper.Map(dc.Courses.FirstOrDefault(c=>c.Id==Id));
}
尝试使用
Attach()
而不是
Add()

Add()
用于数据库中不存在的新对象<代码>附加()用于创建与数据库中已存在的实体的关系

编辑

在没有看到您的代码的情况下,我建议附加的最佳解决方案是创建一个“存根”实例,然后将其附加到您的
newCancellation

var existingCourse = new Course{ Id = newCancellation.ClassCancelled.Course.Id };
db.Courses.Attach(existingCourse);
newCancellation.Course = existingCourse;

我发现最简单的解决方案是在更新模型时,清除所有相关实体,然后重新添加它们

即:


问题是您有多个上下文或工作单元。将newCancellation添加到dc上下文时,它还会在对象图中添加dc上下文中未跟踪的任何相关实体。我认为你最好的选择是:

dc.ClassCancellations.Add(newCancellation);
dc.Entry(newCancellation.Course).State = EntityState.Unchanged;
dc.Entry(newCancellation.Faculty).State = EntityState.Unchanged;
有关说明和其他选项,请参阅


在我看来,EF应该识别具有自动编号键的实体,而不是在指定键的情况下插入它们。

我已经编辑了您的标题。请看“”,其中的共识是“不,他们不应该”。谢谢约翰。我不熟悉这个^。^那些教员和课程对象来自哪里?它们是否已连接?教员和课程对象从数据库中检索,然后映射到其他repo方法中的viewmodels。编辑:试图澄清一点-。-Mapper.Map是否创建了一个具有一些DBs属性的全新对象,但没有必要的EF属性来说明它已经存在于DB中?因此,它一直在添加新对象。
newCancellation
对象是全新的,需要保存。它的一些属性引用了数据库中已经存在的对象。感谢您让我注意到
Attach()
,这可能会帮助我解决另一个问题。您能否显示教员和课程对象的设置位置?它们是在最初通过实体
dbcontext
对数据库进行种子设定时创建的。我将添加代码,在viewmodel表单中检索它们。嘿,除非你真的认为这会有帮助。我会粘贴整个内容,但是这个页面会变得很长:p这对我不起作用。它引发异常(
InvalidOperationException
),说明保存或接受更改失败,因为“IntAssignment.Models.Faculty”类型的多个实体具有相同的主键值。
    public CourseForList getForList(int? id)
    {
        return Mapper.Map<CourseForList>(dc.Courses.FirstOrDefault(c => c.Id == id));
    }
dc.ClassCancellations.Attach(newCancellation);
dc.SaveChanges();
var existingCourse = new Course{ Id = newCancellation.ClassCancelled.Course.Id };
db.Courses.Attach(existingCourse);
newCancellation.Course = existingCourse;
 newCancellation.Students.Clear();

 foreach ( var student in students )
 {
     newCancellation.Students.Add(student);
 }
dc.ClassCancellations.Add(newCancellation);
dc.Entry(newCancellation.Course).State = EntityState.Unchanged;
dc.Entry(newCancellation.Faculty).State = EntityState.Unchanged;