Установить значение как неизмененное, если значение свойства равно

У меня проблема с переносом дочерних объектов от одного родителя к другому из-за того, что дочерний объект имеет составной первичный ключ, который также является частью внешнего ключа.

Технически говоря, это та же проблема, что и Entity Framework: Отменить изменение свойства, если значение не изменилось

Но с того 8 лет прошло, и какие-то другие решения теперь должны существовать?

Лучшее решение, которое я придумал до сих пор, это:

    public void CleanModified()
    {
        foreach (var entityEntry in ChangeTracker.Entries()
                                .Where(w => w.State.HasFlag(EntityState.Modified)))
        {
            foreach (var currentValuesPropertyName in entityEntry.CurrentValues
                                                                    .PropertyNames)
            {
                var nop = entityEntry.Property(currentValuesPropertyName);

                if (!nop.IsModified)
                    continue;

                if (Object.Equals(nop.CurrentValue, nop.OriginalValue))
                    nop.IsModified = false;
            }
        }
    }

К сожалению, это не работает и просто выдает то же самое исключение, которое я получил в первую очередь на nop.IsModified = false;

The property '[CompositeKeyProperty]' is part of the object's key information 
and cannot be modified

Я ничего не работал с T4, поэтому не знаю, может ли это помочь мне в этом случае?

Добавлен следующий пример:

Сущности

public class Parent
{
    public int TenantId { get; set; }
    public int Id { get; set; }

    public virtual ICollection<Child> Children { get; set; }
}

public class Child
{
    public int TenantId { get; set; }
    public int Id { get; set; }
    public int ParentId { get; set; }

    public virtual Parent Parent { get; set; }
}

Сопоставления

public class ParentConfiguration : EntityTypeConfiguration<Parent>
{
    public ParentConfiguration()
    {
        HasKey(k => new { k.TenantId, k.Id });

        Property(p => p.TenantId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

public class ChildConfiguration : EntityTypeConfiguration<Child>
{
    public ChildConfiguration()
    {
        HasKey(k => new { k.TenantId, k.Id });

        Property(p => p.TenantId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        HasRequired(r => r.Parent).WithMany(m => m.Children)
            .HasForeignKey(f => new { f.TenantId, f.ParentId });
    }
}

Программа

public void Main()
{
    //Just example, fetched from database in real code
    Parent parentOld = new Parent
    {
        TenantId = 1,
        Id = 1,
        Children = { new Child { TenantId = 1, Id = 1, ParentId = 1 } }
    };

    Parent parentNew = new Parent { TenantId = 1, Id = 2 };

    //Move child from oldParent to newParent
    foreach (var parentOldChild in parentOld.Children)
    {
        //Throws 'The property 'TenantId' is part of the object's key information 
        //and cannot be modified'
        parentOldChild.Parent = parentNew; 
    }
}

person Erik Karlsson    schedule 21.04.2017    source источник
comment
Вы случайно ссылались на один и тот же объект ChangeTracker более одного раза, чтобы проверить измененное состояние (в другом контексте)? Часто эта ошибка возникает в цикле foreach и устраняется путем назначения нового экземпляра этого объекта внутри тела цикла.   -  person Tetsuya Yamamoto    schedule 21.04.2017
comment
@TetsuyaYamamoto Нет, все это находится в одном и том же контексте, и доступ направляется непосредственно в базовый DbContext.   -  person Erik Karlsson    schedule 21.04.2017


Ответы (1)


Ошибка сообщает вам, что проблема связана с тем, что вы пытаетесь установить состояние IsModified для поля, которое является частью ключевых столбцов сущности. Вы уверены, что объект, на который вы смотрите, не новый? Это может быть сценарий, когда CurrentValue равно OriginalValue, но IsModified по-прежнему верно и не может быть изменено.

person ErikE    schedule 21.04.2017
comment
Добавлен еще один пример кода, первый пример кода пытается отменить изменение, вызванное вторым примером, касаясь «TenantId», он запускает обновление изменения в отслеживании изменений. - person Erik Karlsson; 21.04.2017
comment
Является ли TenantId частью ключа таблицы? - person ErikE; 21.04.2017
comment
Да, я обновил пост с упрощенным примером - person Erik Karlsson; 23.04.2017