问题
I am trying to do a simple update to the foreign key but the script never get sent over.
Here is the code I am using:
using (var db = new MyContext())
{
db.Entry<Contact>(newContact).State = EntityState.Modified;
newContact.ContactOwner = db.Person.Find(3);
db.SaveChanges();
}
EF6 update the rest of the column in the Persons table but it is not updating the Contact_Id in Persons table.
Person entity:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public List<Contact> ContactList { get; set; }
}
Contact entity:
public class Contact
{
public int Id { get; set; }
public string Email { get; set; }
public string TelNo { get; set; }
public Person ContactOwner { get; set; }
}
What am I missing here?
Please help!
回答1:
Since you are working with independent association. You can either
Adding and removing the relationship from
ContactList
, but you need to retrieve from bothPerson
.db.Entry(newContact).State = EntityState.Modified; var p1 = db.Set<Person>().Include(p => p.ContactList) .FirstOrDefault(p =>p.Id == 1); p1.ContactList.Remove(newContact); var p3 = db.Set<Person>().Include(p => p.ContactList) .FirstOrDefault(p => p.Id == 3); p3.ContactList.Add(newContact); db.SaveChanges();
Or you can use disconnected object, but you need to manually manage the relationship.
db.Entry(newContact).State = EntityState.Modified; var p1 = new Person { Id = 1 }; db.Entry(p1).State = EntityState.Unchanged; var p3 = new Person { Id = 3 }; db.Entry(p3).State = EntityState.Unchanged; var manager = ((IObjectContextAdapter)db).ObjectContext.ObjectStateManager; manager.ChangeRelationshipState(newContact, p1, item => item.ContactOwner, EntityState.Deleted); manager.ChangeRelationshipState(newContact, p3, item => item.ContactOwner, EntityState.Added); db.SaveChanges();
PS
You might need to reconsider adding foreign key value, to make everything easier, updating foreign key just by mentioning the Id.
See this post for more information.
回答2:
This is what I ended up building till the late hours of the morning, chould/should be refactored some more...
protected static async Task<int> SaveEntity<t>(t obj) where t : BaseModel
{
try
{
using (DatabaseContext db = GetDbContext())
{
//get the basemodel/fk reference properties
IEnumerable<PropertyInfo> props = obj.GetType().GetProperties().Where(p => p.PropertyType.BaseType == typeof(BaseModel));
if (obj.Id <= 0)
{//insert
db.Entry(obj).State = EntityState.Added;
//set fk reference props to unchanged state
foreach (PropertyInfo prop in props)
{
Object val = prop.GetValue(obj);
if (val != null)
{
db.Entry(val).State = EntityState.Unchanged;
}
}
//do insert
return await db.SaveChangesAsync();
}
else
{//update
//get the posted fk values, and set them to null on the obj (to avaid dbContext conflicts)
Dictionary<string, int?> updateFKValues = new Dictionary<string, int?>();
foreach (PropertyInfo prop in props)
{
BaseModel val = (BaseModel)prop.GetValue(obj);
if (val == null)
{
updateFKValues.Add(prop.Name, null);
}
else
{
updateFKValues.Add(prop.Name, val.Id);
}
prop.SetValue(obj, null);
}
//dbContext creation may need to move to here as per below working example
t dbObj = (t)db.Set(typeof(t)).Find(new object[] { obj.Id }); //this also differs from example
//update the simple values
db.Entry(dbObj).CurrentValues.SetValues(obj);
//update complex values
foreach (PropertyInfo prop in props)
{
Object propValue = null;
if (updateFKValues[prop.Name].HasValue)
{
propValue = (BaseModel)db.Set(prop.PropertyType).Find(new object[] { updateFKValues[prop.Name] });
}
prop.SetValue(dbObj, propValue);
if (propValue != null)
{
db.Entry(propValue).State = EntityState.Unchanged;
}
}
//do update
return await db.SaveChangesAsync();
}
}
}
catch (Exception ex)
{
ExceptionHelper.Log(ex);
throw;
}
}
回答3:
Basically this happens because EntryState.Modified
just looks for scalar properties (primitive types) and with independent association (your case) you don't have it.
There is a several ways to achieve this, @Yuliam has pointed some of them and here you can find more.
来源:https://stackoverflow.com/questions/25417849/unable-to-update-foreign-key-in-entity-framework-6