简体   繁体   中英

Pattern for updating partial entities using Entity Framework

I'm trying to find a pattern that I can implement to quickly allow partial updates to entities using Entity Framework. I can use Attach when I have the full object, but if I'm only doing a partial update, I'd like to find a way to do it in a repeatable manner without specifying the changed properties every time.

I found this idea , and really like it, but I'm struggling to get the "OriginalValues" and "CurrentValues" to be different, they always match. How should I be retrieving entities in order for an update method like this to work?

I retrieve the data and use it to populate information on a page (but the user can change/view only part of the entity), so I only get back partial entity information on the post-back - do I have to retrieve and detach the entity before updating like this? I can't use Try/UpdateModel because I'm not doing this work in a controller. Any ideas or alternate patterns would be appreciated.

public virtual void Update(T entity, params Expression<Func<T, object>>[] updatedProperties)
{
    //Ensure only modified fields are updated.
    var dbEntityEntry = DbContext.Entry(entity);
    if (updatedProperties.Any())
    {
        //update explicitly mentioned properties
        foreach (var property in updatedProperties)
        {
            dbEntityEntry.Property(property).IsModified = true;
        }
    }
    else
    {
        //no items mentioned, so find out the updated entries
        foreach (var property in dbEntityEntry.OriginalValues.PropertyNames)
        {
            var original = dbEntityEntry.OriginalValues.GetValue<object>(property);
            var current = dbEntityEntry.CurrentValues.GetValue<object>(property);
            if (original != null && !original.Equals(current))
                dbEntityEntry.Property(property).IsModified = true;
        }
    }
}

It looks like this may have been a duplicate question. I found an answer here .

For the comparison of the updated properties with the values in the database you must reload the document from the database. One example:

public ActionResult Edit(Document document, bool sendEmail, string commentsTextBox)
    {
        if (ModelState.IsValid)
        {
            var documentInDB = docsDB.Documents.Single(d => d.Id == document.Id);

            docsDB.Entry(documentInDB).CurrentValues.SetValues(document);

            foreach (string propertyName in docsDB.Entry(documentInDB)
                                            .OriginalValues.PropertyNames)
            {
                var OriginalValue = docsDB.Entry(documentInDB)
                                    .OriginalValues.GetValue<object>(propertyName);
                var NewValue = docsDB.Entry(documentInDB)
                               .CurrentValues.GetValue<object>(propertyName);

                if (!OriginalValue.Equals(NewValue))
                {
                    //capture the changes
                }
            }
        }
    }

Obviously to implement in a business layer like I was trying to accomplish, you'd have to pass both the database version and the updated version into the method that compares.

I'll update the code once I've tested and have a working sample.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM