清理方法以更新实体框架中的集合

时间:2013-09-10 15:58:32

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

对不起,如果已经提出这个问题,但我在实体框架中更新集合的方法遇到了麻烦。

让我解释一下情况:   - 例如,我有一个带有一些属性的模型CUSTOMER和一个ORDERS集合(例如)。   - 让我们想象一下,我们有一个管理页面,我们可以为客户编辑所有ORDERS,当我们提交表单时,它会向我们发送带有更新ORDERS的对象CUSTOMERS(一些已添加,一些更新,一些删除)。

目前我使用类似的东西来比较旧集合和新集合,并确定我需要删除/更新/添加哪个对象

 var toRemove = new List<ORDERS>();
        var toAdd = new List<ORDERS>();
        foreach (
            var order in
                oldList.Where(
                    order =>
                    newList.FirstOrDefault(t => t.link_id == order.link_id) == null))
        {
            toRemove.Add(order);
        }
        foreach (
            var order in
                newList.Where(
                    order =>
                    oldList.FirstOrDefault(t => t.link_id == order.link_id) == null))
        {
            toAdd.Add(order);
        }
        foreach (var ORDERSe in toRemove)
        {
            bdd.ORDERS.Remove(ORDERSe);
        }
        foreach (var ORDERSe in toAdd)
        {
            ORDERSe.pjt_id = project_id;
            bdd.ORDERS.Add(ORDERSe);
        }

        foreach (
            var order in
                newList.Where(
                    order =>
                    oldList.FirstOrDefault(t => t.link_id == order.link_id) != null))
        {
            var child = oldList.FirstOrDefault(t => t.link_id == order.link_id);
            bdd.Entry(child).CurrentValues.SetValues(order);
        }

但我对此感到不自然,因为在我看来,实体框架应该能够为我做好工作!

我希望有类似的东西:

customer.orders = newOrders;

我是否错过了任何有关实体框架的内容? 因为当我这样做时,它只是复制我的订单。 提前感谢您的回答。

2 个答案:

答案 0 :(得分:1)

你当然可以使用.Except()和.Intersect()来使它更清晰,但这个概念并没有真正改变,AFAIK你还需要单独删除,更新和放大。在循环中添加条目......

var oldList = new List<ORDERS>();
var newList= new List<ORDERS>();

var IdsToRemove = oldList.Select(t => t.link_id).Except(newList.Select(t => t.link_id));
var IdsToAdd = newList.Select(t => t.link_id).Except(oldList.Select(t => t.link_id));
var IdsToUpdate =  newList.Select(t => t.link_id).Intersect(oldList.Select(t => t.link_id));

//remove
bdd.orders.where(x => IdsToRemove.Contains(x.link_id)).ForEach(x => bdd.Remove(x));
//add
foreach(var order in newList.Where(x -> IdsToAdd.Contains(x.link_id))
{
   bdd.Orders.Attach(order);
   bdd.Entries(order).EntityState = EntityState.Added;
}
//update
foreach(var order in newList.Where(x -> IdsToUpdate .Contains(x.link_id))
{
   bdd.Orders.Attach(order);
   bdd.Entries(order).EntityState = EntityState.Modified;
}

bdd.SaveChanges();

答案 1 :(得分:0)

  

但我对此感到不自在,因为在我看来,实体框架   应该能够为我做的工作!

事实上,EF为你做了工作。使用数据上下文SaveChanges方法EF应该能够一次保存所有更改:

DbContext.SaveChanges()

为了您的方便,您仍然可以覆盖此方法。在内部你应该使用这样的东西:

public override int SaveChanges()
{
   var changeSet = ChangeTracker.Entries<IAuditable>();

   if (changeSet != null)
   {
      foreach (var entry in changeSet.Where(c => c.State != EntityState.Unchanged))
      {
          entry.Entity.ModifiedDate = DateProvider.GetCurrentDate();
          entry.Entity.ModifiedBy = UserName;
      }
   }
   return base.SaveChanges();

}