2010-04-27 188 views
0

我建立ASP.NET MVC2应用程序,并使用实体框架的ORM。我有麻烦更新数据库中的对象。每次尝试entity.SaveChanges()时,EF都会在表中插入新行,而不管我想要更新,还是插入即可完成。我想(在接下来的例子等)对象的实体连接,但是后来我如何使用实体框架从asp.net MVC2更新数据库中的模型?

{"An object with a null EntityKey value cannot be attached to an object context."} 

这里是我的插入和更新的简单的功能(这不是真正的汽车,但它是简单的这样来解释,虽然我不要认为这影响答案的话)......

 public static void InsertOrUpdateCar(this Vehicles entity, Cars car) 
    { 
     if (car.Id == 0 || car.Id == null) 
     { 
      entity.Cars.AddObject(car); 
     } 
     else 
     { 
      entity.Attach(car); 
     } 
     entitet.SaveChanges(); 
    } 

我使用AttachTo(“汽车总动员”,汽车),甚至尝试过,但我得到了同样的异常。

任何人有这方面的经验?

回答

1

如果要更新现有的记录,那么你应该有你正在为你的InsertOrUpdate方法的对象实例中的EntityKey。回到你的代码,看看你是否能找到丢失的地方。我怀疑你是向用户呈现一个表单更新此对象,然后映射响应场回一个Car对象,但你没有通过的EntityKey与它(你可能不希望它显示给用户)。

你需要做的是包括使用“隐藏”的输入型形式的关键。您可以使用Html帮助程序Html.Hidden(“Key field name”,key field value)来确保将其传递给用户表单,然后返回到Post代码。

+0

是的,我有强类型的视图,我有HttpPost方法从该窗体获取Car对象。 PK在那里,它是正确的(我已经使用隐藏字段),但EntityKey为空。我不知道为什么它丢失,也不知道在哪里:S – Eedoh 2010-04-27 11:25:16

+0

忘记更新...这是问题所在。需要使用相同的实体密钥进行更改并保存在对象上。 – Eedoh 2010-06-09 08:31:34

3

我可以给你一个粗略的指南,但你的代码上面不给我一堆的工作。

你会想要做这样的事情:

using(Entities dataModel = new Entities()) 
{ 
    if(car.Id == 0 || car.Id == null) 
    { 
     dataModel.AddToCars(car); /* There should be a generated method similar to 
     this that just takes a car object minus the Primary Key */ 
    } 
    else 
    { 
     var selectedCar = dataModel.Cars.Where(x => x.Id == car.Id).FirstOrDefault(); 

     if(selectedCar != null) 
     { 
      selectedCar.Name == car.Name; 
      // Continue updating your car stuff 
     } 
    } 

    dataModel.SaveChanges(); 
} 
+0

嗯,我之前正在考虑这种方法,但它看起来像一个“解决方法”,我想用一些更好,更传统的方法。但是,您的答案很有用。谢谢,这里投票了。 – Eedoh 2010-04-27 11:18:28

+0

我试过这个解决方法,并且在异常消息中再次失败: “操作失败:无法更改关系,因为一个或多个外键属性是不可空的当对关系进行更改时,相关的外键属性被设置为空值,如果外键不支持空值,则必须定义新的关系,必须为外键属性指定另一个非空值,或者不相关的对象必须被删除“。 – Eedoh 2010-04-27 12:02:24

+0

这听起来像是模式定义的问题,以及EF数据模型生成器如何从模式生成代码。我会确保你所有的关系都在edmx中定义好,并且当你在dataModel中添加/更新实体时,每个关系都有适当的数据。 这是EF的黑暗面。 – Tejs 2010-04-27 12:05:34

1

另一种办法,有些人可能会考虑多一点优雅是:

IContext context = ContextFactory.GetContext(); 
EntityRepo repo = new EntityRepo(context); //Entity Repository 
OtherTableEntity y = new OtherTableEntity() //this could be some other derived value you already have 
//that uniquely identifies the record (or foreign key or other value you want to update) 
Int32 id = 1234; //value to update to 
var z = repo.TableToUpdate.List().Where(x => x.FK_ID == y.FK_ID).FirstOrDefault(); 
if (z != null) 
{ 
    z.FK_ID = id; 
    repo.Commit(); 
} 

把休息之前和repo.Commit();后,有你的SQL查询窗口开放之前和之后repo.Commit()运行选择假表。

添加条件基本上你想他们是什么。致电repo.EntityToUpdate.Add(entity)repo.Commit()

相关问题