简体   繁体   English

使用实体框架更新部分实体的模式

[英]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. 我正在尝试找到一种可以实施的模式,以快速允许使用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. 当我拥有完整的对象时,我可以使用Attach,但是如果我只进行部分更新,我想找到一种方法,以一种可重复的方式进行,而不必每次都指定更改的属性。

I found this idea , and really like it, but I'm struggling to get the "OriginalValues" and "CurrentValues" to be different, they always match. 我发现了这个想法 ,并且真的很喜欢它,但是我一直在努力使“ OriginalValues”和“ CurrentValues”不同,它们总是匹配的。 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. 我不能使用Try / UpdateModel,因为我没有在控制器中执行此工作。 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. 经过测试并有可用的示例后,我将更新代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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