带有实体框架的强类型ASP.NET MVC

时间:2009-05-22 20:04:39

标签: c# .net asp.net asp.net-mvc entity-framework

此代码无法实际保存任何更改:

//
// 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将对象模型创建为部门类型EntityObject,其EntityState值为已分离

使用 AttachTo 方法后,其EntityState变为未更改

MSDN on Attaching Objects (Entity Framework)

  

对象附加到对象   未更改状态中的上下文。

由于未更改状态, ApplyPropertyChanges 方法不执行任何操作。

我希望它具有状态已修改

MSDN on EntityState Enumeration

  

独立式
  该对象存在但Object未跟踪它   服务。实体处于此状态   创建后立即创建   并在将其添加到对象之前   上下文。一个实体也在此   它被取消后的状态   调用Detach的上下文   方法或如果使用a加载   NoTrackingMergeOption。

     

不变
  该对象自加载后尚未修改   上下文或自上次以来   SaveChanges方法是   调用。

     

修饰
  对象已更改,但SaveChanges方法尚未更改   被叫了。

我无法将EntityObject的EntityState属性显式设置为已修改。它是只读的。

使用EntityObjects的强类型MVC控制器是不是不可能?

5 个答案:

答案 0 :(得分:8)

您需要从ObjectContext获取ObjectStateManager。使用ObjectStateManager,您可以显式设置对象的状态,而无需调用数据库:

[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");
}

ObjectStateEntry还允许您通过SetModifiedProperty应用更细粒度的状态更改数据。如果调用SetModified,EF会将整个实体视为已修改,并将每个属性保留到数据存储中。使用SetModifiedProperty,EF可以优化查询,并且只涉及实际更改的属性。使用SetModifiedProperty显然更复杂,因为您通常需要知道每个属性的原始值。

我希望这会有所帮助。 ObjectStateManager是EF工具箱中一个功能强大的小工具,可以帮助提高EF v1.0的病态性能和效率。

答案 1 :(得分:3)

我发现上述内容似乎都不适用于我,但MSDN指南示例确实是您从上下文中获取原始项目的位置,然后附加更新的项目。

第二个例子:

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

}

答案 2 :(得分:1)

这有效:

//
// 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");
}

但是有没有办法不查询数据库?

答案 3 :(得分:1)

如果添加一行会发生什么:

[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");
}

状态是否会改变?

答案 4 :(得分:1)

我有这个工作,但我无法得到的是SalesOrderDetail的父实体 我怎么能得到它?

SalesOrderDetail.SalesOrderHead为null,并且entityreference为null。 我的编辑例程只能访问SalesOrderDetail的id。

由于 斯