我有一个CustomerOrder视图,我想更改现有的CustomerOrder。
我有一个非常简化的viewmodel看起来像这样:
public class CustomerOrderViewModel
{
public int ID { get; set; }
public Customer Customer { get; set; }
public DateTime Date { get; set; }
public IEnumerable<OrderRow> OrderRows { get; set; }
}
public class OrderRow
{
public int id { get; set; }
public int price { get; set; }
}
public class Customer
{
public string Name { get; set; }
}
我还有一个包含映射表/字段的数据库。
在我的GET操作方法中,我在Automapper的帮助下加载订单,如下所示:
var customerOrder = using (var ctx = new My_Entities()) {
return ctx.CustomerOrders.
Include("Orderrows").
Include("Customer").
Single(o => o.CustomerOrderID == id);
}
var model= AutoMapper.Mapper.DynamicMap<DataAccessLayer.CustomerOrder, CustomerOrderViewModel>(customerOrder);
在视图中我使用Knockout绑定到那里的viewmodel,用户可以在其中更新CustomerOrder。这包括编辑客户信息和添加新的订单等。
然后在帖子中将ViewModel映射回ObjectContext CustomerOrder:
var customerOrderToBeSaved =
AutoMapper.Mapper.DynamicMap<CustomerOrderViewModel, CustomerOrder>(
customerOrderViewModel);
try
{
using (var ctx = new MyEntities())
{
ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.CustomerOrders.ApplyCurrentValues(customerOrderToBeSaved);
...
ctx.SaveChanges();
}
}
我收到错误消息: ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。
好的,我能理解。但是我应该怎么做呢?我可以获取现有对象并将更改应用于该对象,因为这确实是我想要的。我试图查找旧的并分离它,但我还没有把它弄糟。也许我是以一种完全错误的方式做到这一点。请指教。答案 0 :(得分:3)
您不应附加customerOrderToBeSaved
,请参阅MSDN有关ApplyCurrentValues
的论据。
分离的对象,它具有要应用于原始对象的属性更新。
因此,您必须将实体从数据库加载到上下文中,然后使用具有新值的分离对象加载ApplyCurrentValues
。
答案 1 :(得分:1)
您没有从数据库加载行来更新它。
您可以这样做:
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.Entry( entity ).State = EntityState.Modified;
ctx.SaveChanges();
这将告诉EF发出一个UPDATE SQL语句,该语句会覆盖记录中所有列。
您可以选择要更新的列:
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
var entry = ctx.Entry( entity );
entry.Property( o => o.<ColumnPropertyToUpdate> ).IsModified = true;
entry.Property( o => o.<ColumnPropertyToUpdate> ).IsModified = true;
...
ctx.SaveChanges();
如果您这样做,EF将仅包含您在UPDATE语句中标记为已修改的列。