2011-03-06 177 views
6

你可以找到源代码演示这个问题@http://code.google.com/p/contactsctp5/CTP5 EF代码优先问题

我有三个模型对象。联系,的ContactInfo,ContactInfoType。如果联系人有多个contactinfo,并且每个contactinfo都是contactinfotype。很简单,我猜。我遇到的问题是当我去编辑联系人对象时。我从我的联系人存储库中取出它。然后我运行“UpdateModel(contact);”并用我的表单中的所有值更新对象。 (与调试监控)当我保存更改,虽然,我得到以下错误:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

好像在我称之为更新模型,可以空值了我的引用,这似乎打破一切吗?任何想法如何补救将不胜感激。谢谢。

这里是我的模型:

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

错误与您在表单上进行的更改类型无关吗?我可以想象,如果您从Contact中的集合中删除“ContactInformation”,就会发生这样的错误。如果你只改变表单上的'FirstName'而没有其他的事情发生,错误也会发生吗? – Slauma 2011-03-06 15:48:19

回答

1

感谢Morteza Manavi在实体框架网站上提出这个问题。我的问题是由我的ContactInformation模型属性引起的,'contactid'&'contacttypeid'不可为空。一旦我解决这个问题,UpdateModel()就可以正常工作。非常感谢你!

3

有几件事会在这里。

如果您设置为延迟加载,则只有在您加载子对象时才会加载子对象。这可以通过查询中的以下内容来完成。

..

context.Contacts.Include(c => c.ContactInfos).Include(c => c.ContactInfos.ContactInfoType) 

看到this article对确保对象的全部细节,只要你想被加载。

如果你不希望保存CONTACTINFO和contactinfotype(因为它们没有加载,或者你只是不想),您将需要告诉上下文不救子对象不应该被更新。这是可以做到用:

..

context.StateManager.ChangeObjectState(entity.ContactInfos.ContactInfoType, EntityState.Unchanged); 

我发现我需要改变时/使用国家对象的用户数据做。我绝对不希望被用户更新。

在写一点指导这一切的中间,但直到它在做可能是几个星期我blog

MVC不会存储/发回任何你不投入表格。如果您向对象发送一个对象heirarchy,并且这些值不在隐藏输入中显示,则它们将在您的模型中返回空。出于这个原因,我通常会制作视图模型,这些视图模型只能使用ToEntity和ToModel方法对其进行编辑。这也涵盖了我的安全性,因为我不想在隐藏输入中使用各种用户标识符,只是让我的实体直接映射到MVC(请参阅this article on overposting)。

我会认为你的contactinfo属性设置为虚拟,UpdateModel不会介意它们是否在返回时不存在,但我可能错了,因为我没有尝试过。

+0

我的contactinfo和contactinfotype属性被标记为虚拟。我从上下文中获取我的联系对象,通过一个简单的context.Contact.SingleOrDefault(c => c.ContactId == id); – 2011-03-06 13:29:02

+0

好的,重读我的答案,现在有点歪斜了。你有没有尝试明确包括?我通常在我的仓库GetQuery方法中添加一个默认的加载级别。它看起来像我第一点中的例子。更改yuour context.Contact.SingleOrDefault(c => c.ContactId == id)到context.Contact.Include(c => c.ContactInfos).SingleOrDefault(c => c.ContactId == id) – Gats 2011-03-06 15:45:11

+0

我尝试添加包括,但这并没有改变任何东西,我仍然得到相同的错误。表单中的所有值都正确地映射到person变量,并且在调试时一切看起来都很好。但是,当我preform updatemodel()它似乎空参考,当我保存它失败。 – 2011-03-06 17:33:55