2011-06-07 112 views
0

我一直在努力解決這個問題很長一段時間了。我似乎無法讓我的實體對象在使用UpdateModel()時正確更新。實體框架ModelBinding

我只是不認爲這是一個複雜的數據模型。看起來這應該是一個非常普遍的情況。也許我需要在流暢的api中添加一些東西來消除這個錯誤,但是我無法想象它爲我的生活。

錯誤信息

操作失敗:關係不能被改變,因爲一個或多個外鍵的屬性是不可爲空。當對關係進行更改時,相關的外鍵屬性將設置爲空值。如果外鍵不支持空值,則必須定義新的關係,必須爲外鍵屬性指定另一個非空值,或者必須刪除不相關的對象。

這裏是我的模型和背景:

聯繫人:

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; } 
    } 

ContactInformation:

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

DatabaseContext:

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"); 
} 

FORM DATA

[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" 

UPDATE 相關的一些有趣的細節,以我的問題Here

+3

我的$ 0.02:不要直接綁定到EF實體。使用編輯/查看模型。我不知道你在問什麼,但最終會讓這個問題變得無關緊要。 – 2011-06-07 16:21:45

+0

@Craig Stuntz我沒有任何問題會使這段代碼正常工作。即使發佈這個問題,這是一件令人尷尬的事情。如果我使用視圖模型,您會如何建議將表單中的ContactInformation與正在編輯的聯繫人的聯繫信息進行同步?我接受任何建議。 – 2011-06-07 16:28:18

+0

那麼,在我們走下這條路之前,我想到了另一個想法:你在數據庫中是否有級聯,並且級聯映射是否進入了你的模型?請參閱:http://stackoverflow.com/questions/2477872/problem-with-cascade-delete-using-entity-framework-and-system-data-sqlite – 2011-06-07 16:33:20

回答

0

關係在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)將自行工作。

+0

FWIW我會*仍然*建議使用視圖模型,但這隻會推動這個問題進一步發展;你需要像上面那樣解決它。 – 2011-06-07 18:45:22

+0

首先我真的很感激你花時間看我的代碼。在我的問題中,上面的代碼實際上可以正常工作,它只是IMO糟糕的代碼。理想情況下,我只想說UpdateModel(聯繫人),而MVC負責所有必須弄清哪些實體已被修改/添加/刪除的細節。我討厭我必須直接訪問上下文,並且無法通過對象本身來實現刪除。這似乎很奇怪,與EF你可以輕鬆地做一個contact.ContactInformation.Add(實體),但不是一個contact.ContactInformation.Remove(實體)。 – 2011-06-07 18:55:40

+0

我在這個答案中的評論涉及您的問題中的錯誤消息。更新關係但不刪除對象是我知道會導致該問題的一件事。我懷疑是在做UpdateModel時發生了什麼。即使使用UpdateModel,模型上的級聯應該照顧這個「絨毛」。 – 2011-06-07 19:38:03