Asp.net mvc SaveChanges()异常,投诉缺少已存在的字段

Asp.net mvc SaveChanges()异常,投诉缺少已存在的字段,asp.net-mvc,entity-framework,Asp.net Mvc,Entity Framework,下面的ActionResult过去正常工作,但最近停止工作db.SaveChanges()引发异常,抱怨User和Class字段是必需的。但是他们已经在那里了!如果我简单地将User和Class设置为已经存在的值 item.User = item.User; item.Class = item.Class; 然后例外就消失了。很明显,我误解了这里的一些重大问题。如果这段代码失败,我应该如何更新记录的字段 谢谢你的洞察力 public Ac

下面的ActionResult过去正常工作,但最近停止工作
db.SaveChanges()
引发异常,抱怨
User
Class
字段是必需的。但是他们已经在那里了!如果我简单地将
User
Class
设置为已经存在的值

            item.User = item.User;
            item.Class = item.Class;
然后例外就消失了。很明显,我误解了这里的一些重大问题。如果这段代码失败,我应该如何更新记录的字段

谢谢你的洞察力

    public ActionResult ApproveChange(int id)
    {
        var item = db.EnrollmentItems.FirstOrDefault(x => x.ID == id);

        if (item != null
            && item.State == EnrollmentState.Submitted
            && LoginUser.IsManager(ClientBusiness))
        {
            item.State = EnrollmentState.Approved;
            item.LastTouch = DateTime.UtcNow;
            db.SaveChanges();
            return Json(new { State = item.State });
        }
        return Json(new { State = "error" });
    }
下面是类定义

public class EnrollmentItem
{
    public int ID { get; set; }
    [Required]
    public virtual User User { get; set; }
    [Required]
    public virtual Class Class { get; set; }
    public string Action { get; set; }
    public string State { get; set; }
    public DateTime LastTouch { get; set; }

    public override string ToString()
    {
        return 
            String.Format("{0} {1} {2} {3} {4}",
            User, Action, ID, State, Class);
    }
}

出现此错误是因为实体框架拒绝使用缺少必需属性的模型访问数据库。它为空,因为您从未从数据库中获取过它。

通过将它们设置为自身,您可以调用get方法+set方法,这将触发延迟加载,从数据库中获取用户和类对象。
要直接执行此操作,您可以在firstOrDefault调用中包含这两个属性,如下所示:

var item = db.EnrollmentItems
               .Include(x=>x.User)
               .Include(x=>x.Class)
               .FirstOrDefault(x => x.ID == id);
如果您不想包含它们,我想您也可以在模型上添加外键属性,这样就不必加入表。你的班级看起来是这样的:

public class EnrollmentItem
{
    public int ID { get; set; }

    public virtual User User { get; set; }
    public int UserId{get;set;}
    public virtual Class Class { get; set; }
    public int ClassId{get;set;}
    public string Action { get; set; }
    public string State { get; set; }
    public DateTime LastTouch { get; set; }

    public override string ToString()
    {
        return 
            String.Format("{0} {1} {2} {3} {4}",
            User, Action, ID, State, Class);
    }
}

您必须在映射类中指定所需的,但然后您可以更新并插入虚拟属性或foreignkeyId(实体框架将以某种方式解决)。

这似乎是EF中的一个缺陷…它应该只在我创建新记录时检查这些内容,而不是更新现有记录。此操作应转换为更新表集合字段=值,其中ID=ID,无需联接表和检索更多行。数据库中内置的引用完整性确保现有的用户和类字段有效。EF在将我与实施隔离和强迫额外工作方面做得很差。好的,走开。最后,我应该从哪里知道这一点?假设还有其他EF骗局正在进行中,我是否应该读一些东西?如果说这些字段已经存在的原因是因为调试器调用了
item.ToString()
,从而检索到了它们,是否正确?实际上,它一定对该项的副本调用了ToString(),因为当我通过时,
db.SaveChanges()
仍然抛出异常。很抱歉延迟,我离开了几天。如果您调试或调用ToString,您的延迟加载将为您获取它。不确定他是否克隆了该对象或该对象是否已加载。关于您的rant:您根据需要指定了这些属性,但在unitofwork(上下文)中,您尚未将它们加载到内存中。EF不能仅仅依赖于引用完整性,因为您的上下文和数据库方案可能不同。至于阅读材料,我不是一个大的读者,但我怀疑关于关系的必要属性没有太多使用(至少我没有)。