您可以找到演示此问题的源代码@ http://code.google.com/p/contactsctp5/
我有三个模型对象。联系,的ContactInfo,ContactInfoType。如果联系人有许多contactinfo,并且每个contactinfo都是contactinfotype。我觉得相当简单。我遇到的问题是当我去编辑联系对象时。我从我的联系人存储库中取出它。然后我运行“UpdateModel(contact);”并使用我的表单中的所有值更新对象。 (使用debug进行监视)当我保存更改时,出现以下错误:
操作失败:关系 无法更改,因为一个或 更多的外键属性是 非空的。当进行更改时 关系,相关 foreign-key属性设置为null 值。如果外键没有 支持null值,一个新的 关系必须定义, 必须分配外键属性 另一个非空值,或者 必须删除不相关的对象。
似乎在我调用更新模型之后它将我的引用归零,这似乎打破了一切?任何有关如何补救的想法将不胜感激。感谢。
以下是我的模特:
public partial class Contact {
public Contact() {
this.ContactInformation = new HashSet<ContactInformation>();
}
public int ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<ContactInformation> ContactInformation { get; set; }
}
public partial class ContactInformation {
public int ContactInformationId { get; set; }
public int ContactId { get; set; }
public int ContactInfoTypeId { get; set; }
public string Information { get; set; }
public virtual Contact Contact { get; set; }
public virtual ContactInfoType ContactInfoType { get; set; }
}
public partial class ContactInfoType {
public ContactInfoType() {
this.ContactInformation = new HashSet<ContactInformation>();
}
public int ContactInfoTypeId { get; set; }
public string Type { get; set; }
public virtual ICollection<ContactInformation> ContactInformation { get; set; }
}
我的控制器操作:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Contact person) {
if (this.ModelState.IsValid) {
var contact = this.contactRepository.GetById(person.ContactId);
UpdateModel(contact);
this.contactRepository.Save();
TempData["message"] = "Contact Saved.";
return PartialView("Details", contact);
} else {
return PartialView(person);
}
}
上下文代码:
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder) {
modelBuilder.Entity<Contact>()
.HasMany(c => c.ContactInformation)
.WithRequired()
.HasForeignKey(c => c.ContactId);
modelBuilder.Entity<ContactInfoType>()
.HasMany(c => c.ContactInformation)
.WithRequired()
.HasForeignKey(c => c.ContactInfoTypeId);
}
答案 0 :(得分:3)
这里有一些事情发生。
1 如果设置为延迟加载,则只有在您指示加载时才加载子对象。这可以通过查询中的以下内容完成。
...
context.Contacts.Include(c => c.ContactInfos).Include(c => c.ContactInfos.ContactInfoType)
有关确保根据需要加载对象的详细信息,请参阅this article。
2 如果你不想保存contactinfo和contactinfotype(因为它们没有加载或你只是不想),你需要告诉上下文不要保存子对象不应该更新。这可以使用:
完成...
context.StateManager.ChangeObjectState(entity.ContactInfos.ContactInfoType, EntityState.Unchanged);
我发现在将国家/地区对象更改/使用用户数据时,我需要这样做。我绝对不希望用户更新。
在编写所有这些指南的过程中,可能需要几周才能完成blog
3 MVC不会存储/发送您未放入表单的任何内容。如果将对象层次发送到表单并且值未在隐藏输入中表示,则它们将在模型上返回空白。出于这个原因,我通常只生成只能使用ToEntity和ToModel方法的实体版本的视图模型。这也包含了我的安全性,因为我不希望隐藏输入中存在各种用户ID,因此我的实体直接映射到MVC(请参阅this article on overposting)。
我认为你将你的contactinfo属性设置为虚拟的事实,UpdateModel不会介意它们在返回时是否存在,但我可能错了,因为我没有尝试过。< / p>
答案 1 :(得分:1)
感谢Morteza Manavi在实体框架网站上提出这个问题。我的问题是由我的ContactInformation模型属性'contactid'和&amp; 'contacttypeid'不可为空。一旦我修复了这一切,UpdateModel()工作正常。非常感谢你!