簡體   English   中英

實體框架無法使用復合鍵更新表中的數據(Oracle)

[英]Entity Framework Can't Update Data In Table With Composite Key (Oracle)

我們有一個Oracle表,其中包含三列的復合鍵。 這些列通過實體框架數據模型正確映射到C#對象。 當我們從數據庫查詢記錄然后更新非鍵列時,我們總是會收到一條錯誤消息,說我們正在嘗試更新主鍵(下面是測試的摘錄):

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”是對象的密鑰信息的一部分,無法修改。 at Data.Objects.EntityEntry.VerifyEntityValueIsEditable(StateManagerTypeMetadata typeMetadata,Int32 ordinal,String memberName)

at System.Data.Objects.EntityEntry.GetAndValidateChangeMemberInfo(String entityMemberName,Object complexObject,String complexObjectMemberName,ref StateManagerTypeMetadata typeMetadata,ref String changingMemberName,ref Object changingObject)

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

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

at 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 metadata,Int32 ordinal,Object userObject,Object newValue)

at System.Data.Objects.ObjectStateEntryDbUpdatableDataRecord.SetRecordValue(Int32 ordinal,Object value)

at System.Data.Objects.DbUpdatableDataRecord.SetValue(Int32 ordinal,Object value)

在System.Data.Mapping.Update.Internal.UpdateTranslator.SetServerGenValue(P ropagatorResult context,Object value)

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

在System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntityAdapter adapter)

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

處於System.Data.Entity.InternalContext.SaveChanges()的System.Data.Entity.InternalContext.SaveChanges()處的System.Data.Objects.ObjectContext.SaveChanges(SaveOptions選項)處的System.Data.Entity.LazyInternalContext.SaveChanges()處於System.Data.Entity.DbContext 。保存更改()

更新我們已經跟蹤了數據庫交互,看來以下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 }

請包括:

  • 實體定義
  • 上下文中的映射類/配置
  • SQL表定義

BackPropagateServerGen

查看堆棧跟蹤,我看到的關鍵是BackPropagateServerGen

實體框架正在針對數據庫運行更新,但是您的一個復合鍵值(可能是COPY_ID)實際上正被UPDATE調用更改。 此服務器生成的值將從SQL調用返回,然后實體框架抱怨密鑰值正在從其下面更改。

所以,我猜你的COPY_ID復合鍵值被定義為服務器生成的標識符,但是其中一個或兩個都發生了:

  • 您正在映射到視圖或存儲過程,這會干擾Entity Framework對vanilla UPDATE的期望
  • 您在表,視圖或存儲過程中有一個或多個觸發器干擾結果。

如果您有任何觸發器,請暫時禁用它們以查看問題是否會停止。

如果要映射到視圖或存儲過程,請嘗試直接映射到表。

使用您擁有的任何分析工具來捕獲代碼正在執行的SQL。

摘要

我認為UPDATE調用實際上是到達數據庫,但返回結果是更改鍵值,導致實體框架失敗,並可能回滾UPDATE事務(取決於您使用的EF版本)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM