从 SaveChanges 中拦截和重定向实体保存

Intercept and Redirect Entity save from within SaveChanges

我目前在数据库中有一个 table 结构如下:

Orders
    OrderId int , --Primary Key
    CustomerId int,
    PartId int,
    OrderDate Date,
    Quantity int

不幸的是,因为 OrderId 被设置为主键而不是 CustomerId、PartId 和 OrderDate 的复合键,我们在数据库中有许多以下实例:

OrderId | CustomerId | PartId | OrderDate  | Quantity
1       | 23         | 45     | 2016-11-16 | 1
2       | 23         | 45     | 2016-11-16 | 1
3       | 23         | 45     | 2016-11-16 | 1
4       | 26         | 30     | 2016-10-25 | 1
5       | 26         | 30     | 2016-10-25 | 1

而不是:

OrderId | CustomerId | PartId | OrderDate  | Quantity
1       | 23         | 45     | 2016-11-16 | 3
4       | 26         | 30     | 2016-10-25 | 2

由于 regulatory/logging 问题,我无权更新数据库,更新会破坏遗留代码。然而,我已经说服我的老板允许我更新实体以对任何向前发展的数据实施这些限制。

我的想法是覆盖 DbContext 中的 SaveChanges,这样如果遗留代码试图添加另一行,其中 CustomerIdPartIdOrderDate 已经存在,取消保存并增加现有行的 Quantity 列。到目前为止,我有以下内容,但不确定如何取消保存、更新现有行并强制该行从 SaveChanges.

中保存
public override int SaveChanges()
{

    var PartAssemblyList = ChangeTracker.Entries()
                            .Where( x => x.Entity is Order &&
                                         x.State == EntityState.Added);

    foreach (var entity in PartAssemblyList)
    {
        if (/*RowExists*/)
        {
            //Cancel Save (entity.State = EntityState.Unchanged)?
            //Update Quantity of Existing Row
            //Set existing row to save
        }
    }

    return base.SaveChanges();
}

我认为覆盖 EF 不是一个好主意,因为您可以将它用于 Orders 以外的其他实体。但是,为什么不包装 SaveChanges() 调用并自己完成 add/update 工作呢?

public void AddUpdateOrder(Order o)
{
    using(var ctx = new YourDataModelContext())
    {
        if(ctx.Orders.Any(x => x.OrderId == o.OrderId && x.CustomerId == o.CustomerId && x.PartId == o.PartId && x.OrderDate == o.OrderDate))
        {
            var e = ctx.Orders.Where(x => x.OrderId == o.OrderId && x.CustomerId == o.CustomerId && x.PartId == o.PartId && x.OrderDate == o.OrderDate).FirstOrDefault();
            e.Quantity += 1;
            ctx.Entry(e).State = Modified; 
        }
        else
        {
            Order e = new Order() { OrderId = o.OrderId, CustomerId = o.CustomerId, PartId = o.PartId, OrderDate == o.OrderDate, Quantity = 1};
            ctx.Orders.Add(e);
        }
        ctx.SaveChanges();
    }
}