【问题标题】:Entity Framework with ASP.NET MVC带有 ASP.NET MVC 的实体框架
【发布时间】:2009-05-21 22:26:31
【问题描述】:

如何将强类型控制器与 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 无法跟踪具有相同键的多个对象。”

这应该如何工作?

【问题讨论】:

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


【解决方案1】:

问题是,您所拥有的输入不是具有更改属性的完整模型对象 - 它只是新模型对象的“开始”,具有您想要覆盖现有实体的所有属性。您没有发布任何 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");
}

【讨论】:

  • 这看起来不像是向前迈出了一步;)。
  • 如果重要的是漂亮的代码,那就不行了。这并不漂亮......但它有效,所以与不漂亮的代码相比,我必须说这是一个进步! ;)
【解决方案2】:

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

here所述

“在 ObjectContext 上调用 AttachTo 以将对象附加到对象上下文中的特定实体集。如果对象具有 null(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("客户", 23);

我在自己的 EF 代码中使用了类似的方法,除了使用 Generic 类型参数来避免必须使用字符串作为实体类名称。

【讨论】:

【解决方案3】:

这个怎么样

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

也许 tmp-part 可以在 Attach 部分之后交换为对 UpdateModel 的调用,但我不确定。

编辑:刚刚查看了有关 Attach(Entity e, Entity original) 的文档,它确实用 e 替换了 original(或相应地更新原始文件或 w/e)。

【讨论】:

    【解决方案4】:

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

    也许您应该在之前通过 id 检索一个对象,然后将您通过参数提供的值替换为 edit 方法,然后保存更改。 您收到错误是因为您一开始没有卸载模型。

    [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 获取对象时将其分离,并在要在编辑方法中保存新值时将其附加回来。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-17
      • 2011-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 2011-07-21
      相关资源
      最近更新 更多