Asp.net mvc 4 MVC4和EF5应用更改的最佳实践

Asp.net mvc 4 MVC4和EF5应用更改的最佳实践,asp.net-mvc-4,entity-framework-5,Asp.net Mvc 4,Entity Framework 5,我有一个CustomerOrder视图,我想在其中更改现有CustomerOrder 我有一个非常简单的viewmodel,看起来像这样: public class CustomerOrderViewModel { public int ID { get; set; } public Customer Customer { get; set; } public DateTime Date { get; set; }

我有一个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; }    
    }
  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);
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.Entry( entity ).State = EntityState.Modified;
ctx.SaveChanges();
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();
公共类CustomerOrderViewModel
{
公共int ID{get;set;}
公共客户客户{get;set;}
公共日期时间日期{get;set;}
公共IEnumerable OrderRows{get;set;}
}
公共类OrderRow
{
公共int id{get;set;}
公共整数价格{get;set;}
}
公共类客户
{
公共字符串名称{get;set;}
}
我还有一个带有映射表/字段的数据库

在GET Action方法中,我在Automapper的帮助下加载订单,如下所示:

        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; }    
    }
  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);
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.Entry( entity ).State = EntityState.Modified;
ctx.SaveChanges();
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();
var customerOrder=using(var ctx=new My_Entities()){
返回ctx.CustomerOrders。
包括(“订单行”)。
包括(“客户”)。
单个(o=>o.CustomerOrderID==id);
}
var模型=AutoMapper.Mapper.DynamicMap(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();

            }
        }
var客户订单已保存=
AutoMapper.Mapper.DynamicMap(
customerOrderViewModel);
尝试
{
使用(var ctx=new MyEntities())
{
ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.CustomerOrders.ApplyCurrentValue(customerOrderToBeSaved);
...
ctx.SaveChanges();
}
}
我收到错误消息:ObjectStateManager中已存在具有相同密钥的对象。ObjectStateManager无法使用同一密钥跟踪多个对象。


好的,我能理解。但我该怎么做呢?我是否可以获取现有对象并对其应用更改,因为这才是我真正想要的。我试着查一下旧的,把它拆开,但是我没有办法把它弄清楚。也许我这样做是完全错误的。请给出建议。

您不应附加
客户或保存
,请参阅关于
ApplyCurrentValues
的参数

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


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

您不应该附加
customerOrderToSaved
,请参阅关于
ApplyCurrentValues
的参数

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


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

您没有从数据库加载行以更新它

您可以这样做:

        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; }    
    }
  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);
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.Entry( entity ).State = EntityState.Modified;
ctx.SaveChanges();
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 SQL语句,覆盖记录中的所有列

您可以选择要更新的列,如下所示:

        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; }    
    }
  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);
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.Entry( entity ).State = EntityState.Modified;
ctx.SaveChanges();
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();
var entity=ctx.CustomerOrders.Attach(customerOrderToBeSaved);
var分录=ctx分录(实体);
entry.Property(o=>o.).IsModified=true;
entry.Property(o=>o.).IsModified=true;
...
ctx.SaveChanges();

如果执行此操作,EF将只包括在UPDATE语句中标记为已修改的列。

您没有从数据库加载行以进行更新

您可以这样做:

        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; }    
    }
  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);
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.Entry( entity ).State = EntityState.Modified;
ctx.SaveChanges();
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 SQL语句,覆盖记录中的所有列

您可以选择要更新的列,如下所示:

        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; }    
    }
  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);
var entity = ctx.CustomerOrders.Attach(customerOrderToBeSaved);
ctx.Entry( entity ).State = EntityState.Modified;
ctx.SaveChanges();
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();
var entity=ctx.CustomerOrders.Attach(customerOrderToBeSaved);
var分录=ctx分录(实体);
entry.Property(o=>o.).IsModified=true;
entry.Property(o=>o.).IsModified=true;
...
ctx.SaveChanges();

如果执行此操作,EF将只包括在UPDATE语句中标记为已修改的列。

OK。。。因此,据我所知,我应该做一些类似的事情:var foo=ctx.CustomerOrder.FirstOrDefault(co=>co.ID=ID);ctx.CustomerOrder.ApplyCurrentValues(editedCustomerOrder);var foo2=ctx.Customer.FirstOrDefault(c=>c.ID=foo.CustomerID);ctx.Customer.ApplyCurrentValues(editedCustomerOrder.Customer);等等……我不明白为什么有两次。但本质上是,
editedCustomerOrder
没有附加。FirstOrDefault一个用于CustomerOrder,另一个用于附加的客户。我尝试了包含,但似乎不起作用。好吧。。。因此,据我所知,我应该做一些类似的事情:var foo=ctx.CustomerOrder.FirstOrDefault(co=>co.ID=ID);ctx.CustomerOrder.ApplyCurrentValues(editedCustomerOrder);var foo2=ctx.Customer.FirstOrDefault(c=>c.ID=foo.CustomerID);ctx.Customer.ApplyCurrentValues(editedCustomerOrder.Customer);等等……我不明白为什么有两次。但本质上是,
editedCustomerOrder
没有附加。FirstOrDefault一个用于CustomerOrder,另一个用于附加的客户。我尝试了包含,但似乎不起作用。