3

我有兩個模型類在一到一個關係:[問] asp.net mvc的更新數據庫錯誤

class Person 
{ 
    public int PersonID { get; set; } 
    public int DetailPersonID { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public DetailPerson DetailPerson { get; set; } 
} 

class DetailPerson 
{ 
    public int DetailPersonID { get; set; } 
    public string Address { get; set; } 
    public string PhoneNumber { get; set; } 
} 

和代碼的編輯頁面視圖:

@using (Html.BeginForm()) 
{ 
    @Html.HiddenFor(m => m.PersonID) 

    @Html.LabelFor(m => m.FirstName) 
    @Html.TextBoxFor(m => m.FirstName) 

    @Html.LabelFor(m => m.LastName) 
    @Html.TextBoxFor(m => m.LastName) 

    @Html.LabelFor(m => m.DetailPerson.Address) 
    @Html.TextBoxFor(m => m.DetailPerson.Address) 

    @Html.LabelFor(m => m.DetailPerson.PhoneNumber) 
    @Html.TextBoxFor(m => m.DetailPerson.PhoneNumber) 

    <input type="submit" value="Edit"> 

} 

的EF支架使用此代碼更新數據:

db.Entry(person).State = System.Data.EntityState.Modified; 
db.saveChanges(); 

當我提交的編輯形式,我得到了這樣的錯誤:

無法插入外鍵值,因爲對應的主鍵值不存在。 [外鍵約束名稱= FK_dbo.People_dbo.DetailPersons_DetailPersonID]

但是,如果我這樣做:

Person p = db.Persons.Find(person.PersonID); 
p.DetailPerson = person.DetailPerson; 
p.FirstName = person.FirstName; 
p.LastName = person.LastName; 
db.saveChanges(); 

更新數據成功沒有錯誤

我想知道爲什麼喀斯錯誤的第一種方式, 當我在包含EntityState.Modified, ,但外鍵值(DetailPersonID)爲0的行設置斷點。 然後,我添加了@Htm l.HiddenFor(m => m.DetailPersonID)在編輯窗體上。

我得到另一個錯誤:

參照完整性約束衝突發生了:定義引用約束的屬性值不本金和依賴對象的關係之間是一致的。

我仍然更新數據庫的另一種方式, 我只是很好奇,爲什麼第一種方式是EF標準更新數據有錯誤。

+0

**更新** 我在編輯表單中添加了更多隱藏值,並更新成功 '@ Html.HiddenFor(m => m.DetailPerson.DetailPersonID) @ Html.HiddenFor(m => m.DetailPe rsonID)' 我應該使用這種方式來獲得最佳實踐嗎? – geralvin 2013-03-12 06:12:10

+0

是的。這是預期的方式。沒有Id,EntityFramework不知道要更新哪一個。所以它認爲你正試圖添加一個新的對象到數據庫,而不是更新一個預先存在的對象。 – Aron 2013-03-12 06:50:47

+0

那麼我發現的一件事是,你應該用虛擬標記導航屬性作爲在公共虛擬DetailPerson DetailPerson {get;組; } – 2013-03-12 08:54:43

回答

0

如果存在一對一關係,則不應該使用兩個類,因爲EF會將db標準化爲相應的表單。像這樣組合你的課程。

public class Person 
{ 
    public int PersonID { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Address { get; set; } 
    public string PhoneNumber { get; set; } 
} 

如果你必須有單獨的類(不推薦),像這樣做:

public class Person 
{ 
    public int PersonID { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int DetailPersonID { get; set; } 
    public virtual DetailPerson DetailPerson { get; set; } 
} 

public class DetailPerson 
{ 
    public int PersonID { get; set; } 
    public virtual Person Person { get; set; } 
    public int DetailPersonID { get; set; } 
    public string Address { get; set; } 
    public string PhoneNumber { get; set; } 
} 

然後,當你找回你的對象,像這樣做:

// include the detail when retrieving the parent 
Person person = db.People.Include(p=>p.DetailPerson).Single(p=>p.PersonId == whateverIdYou Need); 

// modify whatever you like 
person.DetailPerson.Address = "my new address"; 

// then your previous statement will work 
db.Entry(person).State = System.Data.EntityState.Modified; 
db.saveChanges();