实体框架ModelBinding

本文关键字:ModelBinding 框架 实体 | 更新日期: 2023-09-27 17:58:39

我已经为这个问题挣扎了很长一段时间了。使用UpdateModel()时,我似乎无法正确更新实体对象。

我只是不认为这是一个复杂的数据模型。这似乎应该是一种非常常见的情况。也许我需要在fluent api的上下文中添加一些内容来消除这个错误,但我一辈子都无法解决。

错误消息

操作失败:由于一个或多个外键属性不可为null,因此无法更改关系。当对关系进行更改时,相关的外键属性将设置为null值。如果外键不支持null值,则必须定义新的关系,必须为外键属性分配另一个非null值,或者必须删除不相关的对象。

以下是我的模型和上下文:

联系人:

public class Contact {
    public Contact() {
      this.ContactInformations = new HashSet<ContactInformation>();
    }
    public int ContactId { get; set; }
    [Required]
    public string Firstname { get; set; }
    [Required]
    public string Lastname { get; set; }
    public virtual ICollection<ContactInformation> ContactInformations { get; set; }
  }

联系信息:

public class ContactInformation {
    public int ContactInformationId { get; set; }
    public int ContactTypeId { get; set; }
    public int ContactId { get; set; }
    [Required]
    public string Information { get; set; }
}

数据库上下文:

public class Database : DbContext {
    public Database()
      : base("Contacts") {
    }
    public DbSet<Contact> Contacts { get; set; }
    public DbSet<ContactInformation> ContactInformations { get; set; }
}

联系控制器

    public ActionResult Edit(int id, Contact form) {
      var contact = db.Contacts.SingleOrDefault(c => c.ContactId == id);
      UpdateModel(contact);
      db.SaveChanges();
      return RedirectToAction("Index");
}

表单数据

[0] "ContactId"  
[1] "Firstname"    
[2] "Lastname"   
[3] "ContactInformations[0].Index" 
[4] "ContactInformations[0].ContactInformationId" 
[5] "ContactInformations[0].ContactId"    
[6] "ContactInformations[0].Information"    
[7] "ContactInformations[0].ContactTypeId"
[8] "ContactInformations[1].Index" 
[9] "ContactInformations[1].ContactInformationId" 
[10] "ContactInformations[1].ContactId"    
[11] "ContactInformations[1].Information"    
[12] "ContactInformations[1].ContactTypeId"

更新与我的问题有关的一些有趣的细节在这里

实体框架ModelBinding

EF中的关系是一级实体。因此,当您断开这个连接时,您必须(1)删除关系,(2)删除实体。在此代码中:

  foreach (var item in needDeleted) {
    //have to use the datacontext directly.  I desperately want this gone!
    db.ContactInformations.Remove(db.ContactInformations.Single(c => c.ContactInformationId == item.ContactInformationId));
    //This will produce the same error as UpdateModel(contact)
    //contact.ContactInformations.Remove(contact.ContactInformations.SingleOrDefault(c => c.ContactInformationId == item.ContactInformationId));
  }

你做了(1)但没有(2)。

可以做:

  foreach (var item in needDeleted) {
    var ci = contact.ContactInformations.Single(c => c.ContactInformationId == item.ContactInformationId);
    contact.ContactInformations.Remove(ci); // 1
    db.ContactInformations.Remove(ci);      // 2
  }

但是,更常见的方法是在FK和模型中的曲面上放置级联。在这种情况下(1)将自行工作。