开发者

Attach entity in modified state without marking all properties dirty

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);

        //开发者_如何学CTODO: 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);
    }
}


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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜