Reputation: 73
I have two model classes in one-to-one relationship:
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; }
}
and the code for the edit page view:
@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">
}
The EF scaffold uses this code to update data:
db.Entry(person).State = System.Data.EntityState.Modified;
db.saveChanges();
When I submit the edit form, I got an error like this:
A foreign key value cannot be inserted because a corresponding primary key value does not exist. [ Foreign key constraint name = FK_dbo.People_dbo.DetailPersons_DetailPersonID ]
But if I do this:
Person p = db.Persons.Find(person.PersonID);
p.DetailPerson = person.DetailPerson;
p.FirstName = person.FirstName;
p.LastName = person.LastName;
db.saveChanges();
update data success without error
I want to know why the first way causse an error, when I set the breakpoint at the line containing EntityState.Modified, but the foreign key value ( DetailPersonID ) is 0. Then, I added @Html.HiddenFor(m => m.DetailPersonID) on the edit form.
I got another error:
A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.
I still update database on the other way, I am just curious why the first way which is EF standart to update data got an error.
Upvotes: 3
Views: 744
Reputation: 1628
You shouldn't use two classes if there is a one-to-one relationship since EF will normalize the db into the corresponding form anyway. Combine your classes like this.
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; }
}
if you must have separate classes (not recommended), do it like this:
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; }
}
Then when you retrieve your object, do it like this:
// 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();
Upvotes: 0