重新附加实体图并检测集合更改 [英] Reattaching an entity graph and detecting collection changes

查看:81
本文介绍了重新附加实体图并检测集合更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我首先使用实体​​框架代码,并通过WCF REST HTTP接口公开罗斯文数据库.

I'm using entity framework code first and exposing the northwind database through a WCF REST HTTP interface.

我没有公开OrderDetails表(订单项),因为创建订单然后通过另一个服务分别添加每个必需的OrderDetail并没有意义.在我看来,它必须是一个成功或失败的原子事务.因此,当传递给客户端时,我将包含Order.OrderDetails集合,并假设在创建或更新订单时会得到一个.

I've not exposed the OrderDetails table (order items) as it doesn't make sense creating an order and then adding each required OrderDetail seperately through another service. To my mind it needs to be an atomic transaction that either succeeds or fails as one. Therefore I include the Order.OrderDetails collection when passing to the client and assume I'm going to get one when an order is created or updated.

但是,问题似乎是在重新附加Order实体进行更新时检测到OrderDetails集合的更改.可以将订单本身设置为修改后的属性,以更新这些属性,但这不会级联到OrderDetail项目.因此,我可以手动检查并设置要更新的更新,但问题在于首先要弄清哪些已更新.设置新的OrderDetail进行修改会在尝试保存时导致错误.

The problem however seems to be detecting changes to the OrderDetails collection when reattaching the Order entity for an update. The order itself can be set as modified to update those properties but this doesn't cascade to the OrderDetail items. So I can manually go through and set updated ones to modified but the problem lies in figuring out which ones are updated in the first place. Setting a new OrderDetail to modified will cause an error when trying to save.

我阅读了一项建议,将新集合项的ID设置为0,然后在服务器中使用该ID来确定它是新的还是现有的.但是,罗斯文(Northwind)使用OrderID和ProductID之间的复合键来订购OrderDetails.这些都必须由客户端设置,所以我找不到检测新内容的方法.此外,已删除的OrderDetail在分离的图中将不存在,我将需要找出已删除的内容并将其明确删除.

I read a recommendation to set the Id of new collection items to 0 and in the server use that to decide whether it's new or existing. Northwind however uses a composite key between OrderID and ProductID for OrderDetails. These will both have to be set by the client, so I can't find a way to detect whats new. Furthermore, a deleted OrderDetail won't exist in the detached graph and I will need to figure out what has been deleted and explicitly remove it.

任何建议将不胜感激.

public override Order Update(Order entity)
{
    dbset.Attach(entity);
    DataContext.Entry(entity).State = EntityState.Modified;

    foreach (var orderDetail in entity.OrderDetails)
    {
        DataContext.Entry(orderDetail).State = EntityState.Modified;
    }

    return entity;
}

推荐答案

这是

This is common and complex issue and there is no magic which will do it for you. My solution (and the only one which works in all scenarios) was to load the Order again in your update method and manually merge changes:

public override Order Update(Order entity)
{
    // No attach of entity

    var attached = DataContext.Orders.Include(o => o.OrderDetails).SingleOrDefault(...);
    if (attached == null) ...

    // Merge changes from entity to attached - if you change any property
    // it will be marked as modified automatically

    foreach (var detail in attached.OrderDetails.ToList())
    {
        // ToList is necessary because you will remove details from the collection

        // if detail exists in entity check if it must be updated and set its state

        // if detail doesn't exists in entity remove if from collection - if it is \
        // aggregation (detail cannot exists without Order) you must also delete it 
        // from context to ensure it will be deleted from the database
    }

    foreach (var detail in entity.OrderDetails)
    {
        // if it doesn't exists in attached create new detail instance,
        // fill it from detail in entity and add it to attached entity - 
        //you must not use the same instance you got from the entity
    }

    DataContext.SaveChanges();

    return entity;
}

如果使用时间戳记,可能还需要手动检查.

There can be also need to manually check timestamps if you use them.

替代方案是您所描述的方案,其中0用于新的详细信息,ID用于删除的详细信息,但这是必须在客户端上完成的逻辑.它也仅在某些情况下有效.

Alternative scenario is what you have described with 0 used for new details and negative ID for deleted details but that is logic which must be done on client. It also works only in some cases.

这篇关于重新附加实体图并检测集合更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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