This code fails to actually save any changes:
//
// POST: /SomeType/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
I found none of the above seemed to work for me, but the MSDN guide example did which is where you get the original item from the context, and then attach the updated item.
Second example:
http://msdn.microsoft.com/en-us/library/bb896248.aspx#Mtps_DropDownFilterText
private static void ApplyItemUpdates(SalesOrderDetail updatedItem){
// Define an ObjectStateEntry and EntityKey for the current object.
EntityKey key;
object originalItem;
using (AdventureWorksEntities advWorksContext =
new AdventureWorksEntities())
{
try
{
// Create the detached object's entity key.
key = advWorksContext.CreateEntityKey("SalesOrderDetail", updatedItem);
// Get the original item based on the entity key from the context
// or from the database.
if (advWorksContext.TryGetObjectByKey(key, out originalItem))
{
// Call the ApplyPropertyChanges method to apply changes
// from the updated item to the original version.
advWorksContext.ApplyPropertyChanges(
key.EntitySetName, updatedItem);
}
advWorksContext.SaveChanges();
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.ToString());
}
}
}
What happens if you add one line:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
db.AttachTo(Model.GetType().Name, Model);
Model.SomeProperty = Model.SomeProperty; // This looks hacky... =(
db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
db.SaveChanges();
return RedirectToAction("Index");
}
Does the state change?
This works:
//
// POST: /SomeType/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
Model.EntityKey = (from SomeType s in db.SomeType
where s.Id == id
select s).FirstOrDefault().EntityKey;
db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
db.SaveChanges();
return RedirectToAction("Index");
}
But is there a way without querying the database?
I have this working, but what iam not able to get at is the parent entity of SalesOrderDetail How can i get at it?
SalesOrderDetail.SalesOrderHead is null and also entityreference is null. My edit routine has access to the id of SalesOrderDetail only.
Thanks Sri
You need to get the ObjectStateManager from your ObjectContext. With the ObjectStateManager, you can explicitly set the state for your object without needing to make a call to the database:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
db.AttachTo(Model.GetType().Name, Model);
ObjectStateManager stateMgr = db.ObjectStateManager;
ObjectStateEntry stateEntry = stateMgr.GetObjectStateEntry(model);
stateEntry.SetModified(); // Make sure the entity is marked as modified
//db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
db.SaveChanges();
return RedirectToAction("Index");
}
The ObjectStateEntry also allows you to apply finer-grained state change data via the SetModifiedProperty. If you call SetModified, EF will treat the entire entity as modified, and persist every property to the data store. With SetModifiedProperty, EF can optimize the queries and only involve the properties that have actually changed. Using SetModifiedProperty is obviously more complex, as you usually need to know the original value of each property.
I hope this helps. ObjectStateManager is a powerful little tool in the EF toolbox, and can help improve EF v1.0's otherwise morbid performance and efficiency.