我们有一个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)
at System.Data.Objects.Internal.SnapshotChangeTrackingStrategy.SetCurrentValue(EntityEntry entry,StateManagerMemberMetadata member,Int32 ordinal,Object target,Object value)
at System.Data.Objects.Internal.EntityWrapper`1.SetCurrentValue(EntityEntry entry,StateManagerMemberMetadata member,Int32 ordinal,Object target,Object value)
at 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)
at System.Data.Mapping.Update.Internal.UpdateTranslator.SetServerGenValue(P ropagatorResult上下文中,对象的值)
at System.Data.Mapping.Update.Internal.UpdateTranslator.BackPropagateServerGen(List`1 generatedValues)
在System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntityAdapter adapter)
at 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()
更新 我们已经跟踪了数据库交互,看来下面的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 }
答案 0 :(得分:2)
请包括:
查看堆栈跟踪,我看到的关键是BackPropagateServerGen
。
实体框架正在针对数据库运行更新,但是您的一个复合键值(可能是COPY_ID)实际上正被UPDATE调用更改。此服务器生成的值将从SQL调用返回,然后实体框架抱怨键值正在从其下面更改。
所以,我猜你的COPY_ID复合键值被定义为服务器生成的标识符,但其中一个或两个都在发生:
如果您有任何触发器,请暂时禁用它们以查看问题是否会停止。
如果要映射到视图或存储过程,请尝试直接映射到表。
使用您拥有的任何分析工具来捕获代码正在执行的SQL。
我认为UPDATE调用实际上是到达数据库,但返回结果是更改键值,导致实体框架失败,并可能回滚UPDATE事务(取决于您的EF版本)使用)。