EF 4: How to properly update object in DbContext using MVC with repository pattern

前端 未结 1 1635
忘了有多久
忘了有多久 2021-02-05 06:52

I\'m trying to implement an AuditLog using the DBContext\'s ChangeTracker object, I ran into an issue where the DbEntityEntry.OriginalValues were getting wiped out

1条回答
  •  野的像风
    2021-02-05 07:31

    it somehow messes up the ChangeTracker's ability to report on the changes

    No it doesn't messes anything. Change tracker ability is based on the fact that change tracker knows the entity prior to making changes. But in your case the change tracker is informed about the entity with changes already applied and POCO entity doesn't keep any information about its original values. POCO entity has only single set of values which is interpreted as both current and original. If you want anything else you must code it yourselves.

    Am I supposed to do the latter example

    In your simple case yes and you can simply use:

    public void SaveProduct(Product product, string userID)
    {
        if (product.ProductID == 0)
        {
            context.Products.Add(product);
        }
        else
        {
            Product prodToUpdate = context.Products
              .Where(p => p.ProductID == product.ProductID).FirstOrDefault();
    
            if (prodToUpdate != null)
            {
                context.Entry(prodToUpdate).CurrentValues.SetValues(product);
            }
        }
    
        context.SaveChanges(userID);
    }
    

    The problem is that this works only for simple and complex properties. Another problem is that this overwrites all properties so if for example your entity has some field you don't want to show in UI (or don't want to let user to edit the field) you must still set correct current value to your product instance otherwise that value will be overwritten when applying current values.

    The whole situation becomes significantly more complex once you try to apply this to the real scenario. You will fail and you will fail many times before you write a lot of code to support exactly your cases because there is probably no generic solution EF has no supporting methods for this scenarios. The reason is that EF has internal state machine for every entity and some associations and you must configure the state for every single entity or association you want to update, insert or delete and you must do it in compliance with EF internal rules. Setting state of the entity will change the state of that single entity but not its relations.

    I do it simply by loading current entity with all relations from database and manually (in code) merging whole entity graph (simply you have detached and attached entity graph and you must transfer all changes from detached to attached one).

    0 讨论(0)
提交回复
热议问题