Прикрепить объект в измененном состоянии, не помечая все свойства как грязные - PullRequest
9 голосов
/ 26 июля 2011

Я пытаюсь выяснить, как пометить определенные свойства отдельного объекта как измененные. Если я сделаю следующее, он пометит все свойства измененными и сгенерированный sql обновит все столбцы.

/// <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;
    }
}

Как установить только измененные свойства как измененные?

Я пытаюсь использовать это в классе, который реализует DbContext, который будет использоваться универсальным репозиторием. Цель состоит в том, чтобы автоматически определить, какие свойства изменились по сравнению со значениями базы данных, а затем установить для этих измененных состояний свойств значение Изменено. В моей текущей реализации метод Modified не знает тип сущности, поэтому я не могу просто получить его с помощью context.Set<T>.Find(key).

Полагаю, я мог бы добавить перегрузку, которая принимает параметр originalEntity, но я бы предпочел этого не делать, если это возможно.

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 Ответ

13 голосов
/ 26 июля 2011

Вы должны сделать это для каждого свойства вручную по телефону:

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
}

Редактировать:

В предыдущем примере предположим, что вы не хотите перезагружать сущность из базы данных, и в этом случае вы должны знать, какие свойства изменены, - вы сами должны ее реализовать.

Если вас устраивает дополнительный запрос к базе данных, вы можете использовать это:

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

Edit2:

Установка исходных значений должна выполняться в обратном порядке (но я никогда не пробовал этого):

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