如何将更改保存到相关表中的MVC 5和6 EF - 实体框架主详细 [英] How to save changes to related table in MVC 5 and EF 6 - Entity Framework Master-Detail

查看:273
本文介绍了如何将更改保存到相关表中的MVC 5和6 EF - 实体框架主详细的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个表,促进和PromotionLine,定义为PromotionLine.PromoID = Promotion.ID

I have two tables, Promotion and PromotionLine, with a foreign key defined as PromotionLine.PromoID = Promotion.ID

PromotionLines与在促进类以下的推广模式有关

PromotionLines are associated with the Promotion model with the following in the Promotion class:

public IList<PromotionLine> PromotionLineItems { get; set; }

我选择不使用虚拟的,因为我不想,如果我们只使用一个摘要视图,显示高层次的促销信息(如促销的列表)加载的宣传片线。

I chose not to use virtual because I don't want the promo lines loaded if we're just using a summary view to show high level Promotion info (such as a list of Promotions).

当需要推广的细节,我得到推广行:

When promotion details are needed, I get the promotion lines:

    public static Promotion GetInstance(int? promotionId)
    {
        if (promotionId == null) return null;
        using (APP01Entities entities = new APP01Entities())
        {
            return entities.Promotions
                .Include(s => s.PromotionState)
                .Include(h => h.PromotionHeaderType)
                .Include(l => l.PromotionLineItems)
                .Include(c => c.PromotionComments)
                .FirstOrDefault(p => p.ID == promotionId);
        }

    }

这工作,我可以在我看来访问推广线。

This works, and I can access the promotion lines in my view.

然而,当我去更新的变化,我遇到的错误:

However, when I go to update changes, I encounter the error:

参照完整性约束冲突发生了:该物业
  Promotion.ID'的值(S)的关系的一端不匹配
  属性值(S)对对方的PromotionLine.PromotionID
  结束。

"A referential integrity constraint violation occurred: The property value(s) of 'Promotion.ID' on one end of a relationship do not match the property value(s) of 'PromotionLine.PromotionID' on the other end."

我明白为什么这个错误发生。我不知道怎么去解决它。
我使用的是默认的更新方法(由EF脚手架创建):

I understand WHY this error is occurring. I don't know how to get around it. I'm using the default update method (created by EF scaffolding):

public bool Update()
    {
        try
        {
            using (APP01Entities entities = new APP01Entities())
            {
                entities.Promotions.Attach(this);

                var entity = entities.ChangeTracker.Entries<Promotion>().FirstOrDefault(e => e.Entity == this);

                if (entity == null)
                {
                    return false;
                }
                entity.State = EntityState.Modified;
                entities.SaveChanges();
            }
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException e)
        {
            throw e.Improve();
        }
    }

的问题是:

entities.Promotions.Attach(this);

这有推广线。 entities.Promotions没有。

"this" has the promotion lines. entities.Promotions does not.

下面是如何我调用更新方法:

Here is how I'm calling the update method:

    [HttpPost]
    public ActionResult Edit(Promotion promotion)
    {
        if (ModelState.IsValid)
        {
            promotion.Update();
        }
        return View(promotion);
    }

问题


  • 如何升迁线路加入到entities.Promotions?

  • 或者,我应该有不同的接近此更新?

推荐答案

这并不是一个简单的任务。您需要更新您的对象图。换句话说,你需要一个主详细更新。

This is not a trivial task. You need to update your object graph. In other word you need a Master-Detail update.

要保持答案简单,我想我有一个订单实体具有订单明细属性,它是一个列表与LT;&的OrderDetail GT; 编辑的时候。你要注意:

To keep the answer simple I suppose I have an Order entity that have OrderDetails property that is a List<OrderDetail>.You should pay attention when editing:


  • 有一些的OrderDetail 已添加到订单明细和他们的主要标志是有编号属性等于0。

  • 某些的OrderDetail 已被删除并不再存在订单明细

  • 某些的OrderDetail 已被更改。

  • There are some OrderDetail that have been added to OrderDetails and the main sign of them is having Id property equal to 0.
  • Some OrderDetail have been removed and no longer exist in OrderDetails
  • Some OrderDetail have been changed.

在更新订单则应该更新订单本身也适用上述变化。

When updating the Order you should update the Order itself and also apply above changes.

步骤

下面是步骤:


  1. 从数据库中获取原始顺序。

  2. 更新使用编辑秩序原订单的价值。

  3. 找到添加的产品清单(添加的项目的ID为0)。

  4. 找到删除的项目清单(原订单的订单详细信息列表,其中的原始顺序细节id是不是编辑订单订单详细信息IDS之间)。

  5. 找到编辑资料(原始顺序,其中的原始顺序细节的id是编辑订单的订单详细信息ID之间的订单详情列表)的列表。

  6. 使用一个遍历删除的项目清单,并设置它们的状态中删除。

  7. 使用循环编辑过的物品清单,并已在上下文中加载的原订单的详细信息更新的价值。

  8. 使用一个循环结束添加的项目清单,并设置他们的状态加入。

  9. 设置原始订单的状态修改。

  10. 保存环境的变化。

code

下面是code:

public void Update(Order editedOrder)
{
    var context = new YourDbContext();

    //Get original order from database.
    var originalOrder = context.Orders.Including("OrderDetails").Where(x => x.OrderId == editedOrder.OrderId).FirstOrDefault();

    //Update the value of original order using edited order.
    context.Entry(originalOrder).CurrentValues.SetValues(editedOrder);

    //Find list of added items (Id of added items is 0).
    var addedList = editedOrder
        .OrderDetails
        .Where(y => y.OrderDetailId == 0)
        .ToList();

    //Find list of removed items.
    var deletedList = originalOrder
        .OrderDetails
        .Where
        (
            x =>
            (
                !editedOrder.OrderDetails
                .Select(y => y.OrderDetailId)
                .Contains(x.OrderDetailId)
            )
        )
        .ToList();

    //Find list of edited items.
    var editedList = editedOrder.OrderDetails
        .Where
        (
            y => originalOrder
            .OrderDetails
            .Select(z => z.OrderDetailId)
            .Contains(y.OrderDetailId)
        )
        .ToList();

    //Use a loop over deleted items list and set state of them to removed.
    deletedList.ForEach(deletedDetail =>
    {
        originalOrder.OrderDetails.Remove(deletedDetail);
        context.Entry(editedOrder).State = EntityState.Deleted;
    });

    //Use a loop over edited items list and update value of original order details  that have been loaded in context.
    editedList.ForEach(editedDetail =>
    {
        var originalOrderDetail = originalOrder.OrderDetails.Where(x => x.OrderDetailId == editedDetail.OrderDetailId).FirstOrDefault();
       context.Entry(originalOrderDetail).CurrentValues.SetValues(editedDetail);
    });

    //Use a loop over added items list and set state of them to added.
    addedList.ForEach(addedDetail =>
    {
        originalOrder.OrderDetails.Add(addedDetail);
    });

    //Set the state of original order to modified.
    context.Entry(oroginalOrder).State = System.Data.Entity.EntityState.Modified;

    //Save context changes.
    context.SaveChanges();
}

这篇关于如何将更改保存到相关表中的MVC 5和6 EF - 实体框架主详细的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆