Подтвердить что ты не робот

Entity Framework не может обновлять данные в таблице с помощью составного ключа (Oracle)

У нас есть таблица Oracle, которая имеет составной ключ из трех столбцов. Эти столбцы корректно отображаются через модель данных Entity Framework в объекты С#. Когда мы запрашиваем запись из базы данных, а затем обновляем не-ключ, всегда получаем ошибку, говорящую о том, что мы пытаемся обновить первичный ключ (выдержка из теста ниже):

var connection = new DbContextProvider(() => new DatabaseConnection()); 
var repo = new Repository(connection); 
var deltas = repo.Queryable<Deltas>().Where(d =>d.Volume.SubmissionId == 88921).ToList();
var deltaToUpdate = deltas.First(); 
deltaToUpdate.RecordedVolume = 0;
repo.Flush();  -- Does a context.SaveChanges() in background

Мы всегда получаем следующее:

System.InvalidOperationException: свойство COPY_ID является частью информация о ключе объекта и не может быть изменена.

COPY_ID является частью ключа, но является StoredGeneratedPettern = Identity и не изменяется в транзакции.

Любая помощь была оценена.

Вот полный стек:

System.InvalidOperationException: свойство COPY_ID является частью информацию о ключе объекта и не может быть изменена. в Data.Objects.EntityEntry.VerifyEntityValueIsEditable(StateManagerTypeMetadata typeMetadata, Int32 ординал, String memberName)

в System.Data.Objects.EntityEntry.GetAndValidateChangeMemberInfo(String entityMemberName, Object complexObject, String complexObjectMemberName, ref StateManagerTypeMetadata typeMetadata, ref String changeMemberName, ref Object changeObject)

в System.Data.Objects.EntityEntry.EntityMemberChanging(String entityMemberName, Object complexObject, String complexObjectMemberName)

в System.Data.Objects.EntityEntry.EntityMemberChanging(String entityMemberName)

в System.Data.Objects.ObjectStateEntry.System.Data.Objects.DataClasses.IEntityChangeTracker.EntityMemberChanging(String entityMemberName)

в System.Data.Objects.Internal.SnapshotChangeTrackingStrategy.SetCurrentValue(запись EntityEntry, член StateManagerMemberMetadata, int32 ординал, цель объекта, значение объекта)

в System.Data.Objects.Internal.EntityWrapper`1.SetCurrentValue(запись EntityEntry, член StateManagerMemberMetadata, int32 ординал, цель объекта, значение объекта)

в System.Data.Objects.EntityEntry.SetCurrentEntityValue(метаданные StateManagerTypeMetadata, int32 ординал, объект ObjectObject объекта, объект newValue)

в System.Data.Objects.ObjectStateEntryDbUpdatableDataRecord.SetRecordValue(Int32 ординал, значение объекта)

в System.Data.Objects.DbUpdatableDataRecord.SetValue(Int32 ординал, значение объекта)

в System.Data.Mapping.Update.Internal.UpdateTranslator.SetServerGenValue(P ropagatorResult контекст, значение объекта)

в System.Data.Mapping.Update.Internal.UpdateTranslator.BackPropagateServerGen(List`1 generatedValues)

в System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, адаптер IEntityAdapter)

в System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)

в System.Data.Objects.ObjectContext.SaveChanges(опции SaveOptions) в System.Data.Entity.Internal.InternalContext.SaveChanges() в System.Data.Entity.Internal.LazyInternalContext.SaveChanges() в System.Data.Entity.DbContext.SaveChanges()

UPDATE Мы проследили взаимодействие db, и кажется, что следующий SQL успешно запущен в базе данных, когда он возвращается в EF, возникает ошибка (и изменение не выполнено):

declare 
"COPY_ID" number(10,0); 
"CODS_ID" number(10,0); 
"PERIOD_ID" number(7,0); 

begin 
  update "SCHEMA"."TABLE" 
  set "COLUMN" = :p0 
  where ((("COPY_ID" = :p1) 
  and ("CODS_ID" = :p2)) 
  and ("PERIOD_ID" = :p3)) 
  returning "COPY_ID", "CODS_ID", "PERIOD_ID" into "COPY_ID", "CODS_ID",  "PERIOD_ID"; 

  open :p4 
    for select "COPY_ID" as "COPY_ID", "CODS_ID" as "CODS_ID",           "PERIOD_ID" as "PERIOD_ID" 
  from dual; 
end; 

{ :p0=[Decimal,0,Input]0, :p1=[Int32,0,Input]222222, :p2=[Int32,0,Input]22222, :p3=[Int32,0,Input]222222, :p4=[Object,0,Output]NULL }
4b9b3361

Ответ 1

Пожалуйста, укажите:

  • Определение сущности
  • Класс отображения/конфигурация из контекста
  • Определение таблицы SQL

BackPropagateServerGen

Глядя на трассировку стека, ключевая вещь, которую я вижу, это BackPropagateServerGen.

Entity Framework запускает ваше обновление по отношению к базе данных, но одно из значений вашего составного ключа (предположительно COPY_ID) фактически изменяется при вызове UPDATE. Это генерируемое сервером значение возвращается из SQL-запроса, и Entity Framework затем жалуется, что значение ключа изменяется из-под него.

Итак, я бы предположил, что ваше составное значение COPY_ID определено как сгенерированный сервером идентификатор, но происходит одно или оба из них:

  • Вы сопоставляете представление или хранимую процедуру, которая мешает тому, что Entity Framework ожидает от ванильного UPDATE
  • У вас есть один или несколько триггеров в таблице, просмотр или хранимая процедура, которые мешают результату.

Если у вас есть триггеры, временно отключите их, чтобы узнать, останавливается ли проблема.

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

Используйте все инструменты профилирования, которые вы должны уловить, что SQL выполняет код.

Резюме

Я думаю, что вызов UPDATE фактически доходит до базы данных, но результат возврата изменяет значение (-ы) ключа, заставляя Entity Framework терпеть неудачу и, вероятно, откатывая транзакцию UPDATE (в зависимости от того, какая версия EF вы используя).