Typed ASP.NET MVC with Entity Framework

This code fails to actually save any changes:

//
// POST: /SomeType/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, SomeType Model)
{
    db.AttachTo(Model.GetType().Name, Model);
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

ASP.NET MVC creates the object Model as a Department type EntityObject with an EntityState value of Detached .

After using the AttachTo method, its EntityState becomes Unchanged .

MSDN on Attaching Objects (Entity Framework)

Objects are attached to the object context in an Unchanged state.

Because of its Unchanged state, the method ApplyPropertyChanges does nothing.

I want it to instead have state Modified .

MSDN on EntityState Enumeration

Detached
The object exists but it is not being tracked by Object Services. An entity is in this state immediately after it has been created and before it is added to the object context. An entity is also in this state after it has been removed from the context by calling the Detach method or if it is loaded using a NoTrackingMergeOption.

Unchanged
The object has not been modified since it was loaded into the context or since the last time that the SaveChanges method was called.

Modified
The object is changed but the SaveChanges method has not been called.

I cannot explicitly set an EntityObject's EntityState property to Modified . It is read only.

Is it just impossible to have strongly-typed MVC controllers with EntityObjects?


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.


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

}


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?

链接地址: http://www.djcxy.com/p/5728.html

上一篇: 获取对实体框架中的对象所做的所有更改

下一篇: 使用实体框架键入ASP.NET MVC