Attach entity in modified state without marking all properties dirty

允我心安 提交于 2019-12-12 10:34:02

问题


I'm trying to figure out how to mark specific properties of a detached entity as modified. If I do the following, it will mark all properties modified and the generated sql will update all columns.

/// <summary>
/// Sets the entity in the modified state.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">The entity.</param>
void IDbContext.Modified<T>(T entity)
{
    DbEntityEntry<T> entry = Entry(entity);
    if (entry.State == EntityState.Modified)
    {
        // if the state is already Modified we don't need to do anything else
        return;
    }

    if (entry.State == EntityState.Detached)
    {
        Set<T>().Attach(entity);

        //TODO: set specific properties modified instead of the the whole object.
        entry.State = EntityState.Modified;
    }
}

How do I set only changed properties as Modified?

I'm trying to use this in a class that implements DbContext that will be used by a generic repository. The goal is to automagically determine which properties have changed compared to the database values and then set those changed properties states to Modified. In my current implementation, the Modified method has no knowledge of the entity type, so I can't simply retrieve it with context.Set<T>.Find(key).

I suppose I could add an overload that accepts an originalEntity parameter, but I'd rather not if possible.

void IDbContext.Modified<T>(T entity, T originalEntity)
{
    DbEntityEntry<T> entry = Entry(entity);
    if (entry.State == EntityState.Modified)
    {
        // if the state is already Modified we don't need to do anything else
        return;
    }

    if (entry.State == EntityState.Detached)
    {
        Set<T>().Attach(entity);

        entry.OriginalValues.SetValues(originalEntity);
    }
}

回答1:


You must do it for each property manually by calling:

DbEntityEntry<T> entry = context.Entry(entity);
if (entry.State == EntityState.Detached)
{
    context.Set<T>().Attach(entity);
    entry.Property(e => e.SomeProperty).IsModified = true;
    // TODO other properties
}

Edit:

Former example suppose that you don't want to reload the entity from the database and in such case you must know which properties are changed - it is up to you to implement it.

If you are happy with additional query to database you can use this:

var persistedEntity = context.Set<T>.Find(key);
var entry = context.Entry(persistedEntity);
entry.CurrentValues.SetValues(entity);

Edit2:

Setting original values should be reverse operation (but I have never tried this):

var persistedEntity = context.Set<T>.Find(key);
context.Entry(persistedEntity).State = EntityState.Detached;

var entry = context.Entry(entity);
context.Set<T>.Attach(entity);
// I'm not sure if you have to change the state of the entity
entry.OriginalValues.SetValues(persistedEntity);


来源:https://stackoverflow.com/questions/6829962/attach-entity-in-modified-state-without-marking-all-properties-dirty

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!