ASP.NET MVC中的Entity Framework

4

如何使用强类型控制器与EntityObjects?

我的失败经历...

首先,我尝试了以下方法:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    db.SaveChanges();
    return RedirectToAction("Index");
}

这并没有实际保存任何更改到数据库中。所以,我试图将模型附加到我的ObjectContext:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    db.Attach(Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

操作失败,因为"带有空EntityKey值的对象无法附加到对象上下文。" 所以我试图分配EntityKey:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    Model.EntityKey = (from Department d in db.Department
                       where d.Id == id
                       select d).FirstOrDefault().EntityKey;
    db.Attach(Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

这个操作失败了,因为“一个具有相同键的对象已经存在于ObjectStateManager中。 ObjectStateManager无法跟踪具有相同键的多个对象。”这是怎么回事呢?

https://dev59.com/b3NA5IYBdhLWcg3wh-cC - Zack Peterson
4个回答

3
事实上,你输入的不是一个完整的模型对象,而是一个新模型对象的“开端”,其中包含要覆盖已有实体上的所有属性。你没有发布任何ID属性,
虽然这看起来有点啰嗦,但这是我找到的最好方法,所以在我的项目中我就这样做(根据你的类名进行调整,缺少的部分自己补充...)。
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    var dbDepartment = (from Department d in db.Department
                        where d.Id == id
                        select d).FirstOrDefault() as Department

    dbDepartment.Name = Model.Name;
    dbDepartment.Color = Model.Color;
    // etc, assigning values manually...

    try
    {
        db.SaveChanges();
    }
    catch (Exception ex)
    {
        // oops...
    }
    return RedirectToAction("Index");
}

3
这似乎并不是一步向前的进展 ;)。 - Morph
1
不过,如果重要的是美丽的代码,那么这并不算美丽。但它能够工作,所以与不能工作的代码相比,我必须说这是一个进步!;) - Tomas Aschan

1

这个怎么样?

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, Department dept)
{
    Department tmp = new Department()
    {
        Id = dept.Id
    };
    try
    {
        db.Departments.Attach(dept, tmp);
        db.Save();
    }
}

也许在 Attach 部分之后,tmp-part 可以被替换为调用 UpdateModel,但我不确定。
编辑:刚刚查阅了 Attach(Entity e, Entity original) 的文档,它确实会用 e 替换 original(或相应地更新 original 等)。

1

尝试使用db.AttachTo()而不是db.Attach()

此处所述

“在ObjectContext上调用AttachTo将对象附加到对象上下文中的特定实体集。如果对象具有空(Visual Basic中的Nothing)EntityKey值,则也要这样做。”

编辑:实际上,在这种情况下,您可能需要调用ApplyPropertyChanges()。

编辑2:您可以使用以下代码为对象构建实体键:

public EntityKey GetEntityKey(string entitySetName, object keyValue)
{
  IEnumerable<KeyValuePair<string, object>> entityKeyValues =
    new[]
    {
      new KeyValuePair<string, object>("Id", keyValue)
    };

  var key = new EntityKey(string.Concat("YOUR_OBJECT_CONTEXT_NAME.", entitySetName), entityKeyValues);
  return key;
}

然后,您可以使用以下类似的代码基于单个数据库列名为“Id”的实体键来调用此函数:

var entityKey = GetEntityKey("Customer", 23);

在我的EF代码中,我使用了类似的方法,但使用了泛型类型参数,以避免使用实体类名称的字符串。


这个可以运行:Model.EntityKey = ...; db.ApplyPropertyChanges("Department", Model); db.SaveChanges(); - Zack Peterson
但是,有没有办法不必执行数据库查询来确定EntityKey? - Zack Peterson
https://dev59.com/aEfRa4cB1Zd3GeqP_LL8 - Zack Peterson
我已经更新了另一个问题:https://dev59.com/aEfRa4cB1Zd3GeqP_LL8 - Zack Peterson

0

我不建议在MVC应用程序中使用POCO。你应该使用DTO或模型。

也许你应该先通过id检索对象,然后用传递给编辑方法的参数替换它的值,然后保存更改。你之所以会出现错误,是因为你一开始没有将模型分离。

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model) {
var entity=from m in db.Models where m.Id == Model.id select m;
Model entityAttached=entity.FirstOrDefault();
//replace all the new values in you object
db.SaveChanges();
}

或者当你通过id获取对象时将其分离,当你想要保存新值时再重新附加回去。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接