1

我有一个 CustomerOrder 视图,我想在其中更改现有的 CustomerOrder。

我有一个非常简化的视图模型,看起来像这样:

        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 绑定到那里的视图模型,用户可以在其中更新 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 无法跟踪具有相同键的多个对象。

好的,我能理解。但是我该怎么做呢?我可以获取现有对象并将更改应用于该对象吗,因为这确实是我想要的。我试图查找旧的并将其分离,但我没有得到它。也许我以完全错误的方式这样做。请指教。

4

2 回答 2

3

您不应该附加customerOrderToBeSaved,请参阅MSDN关于 的论点ApplyCurrentValues

具有属性更新以应用于原始对象的分离对象。

因此,您必须将实体从数据库加载到上下文中,然后ApplyCurrentValues使用具有新值的分离对象。

于 2013-03-02T11:49:41.227 回答
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 语句中标记为已修改的列。

于 2013-03-02T12:07:21.583 回答