我有一个可更新的视图,它映射在实体框架(edmx designer)
中在我将可更新视图(和实体)添加到StoreGeneratedPattern
Computed
var user = objectContext.Users.FirstOrDefault(u => u.Id == 123);
// user is detached and some operations are performed...
// then it's re-attached to a new ObjectContext and has its ObjectStateEntry set to Modified
secondObjectContextInstance.SaveChanges() // throws exception:
The property 'Id' is part of the object's key information and cannot be modified.
at System.Data.Objects.EntityEntry.VerifyEntityValueIsEditable(StateManagerTypeMetadata typeMetadata, Int32 ordinal, String memberName)
at System.Data.Objects.EntityEntry.GetAndValidateChangeMemberInfo(String entityMemberName, Object complexObject, String complexObjectMemberName, StateManagerTypeMetadata& typeMetadata, String& changingMemberName, 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.Mapping.Update.Internal.UpdateTranslator.SetServerGenValue(PropagatorResult context, Object value)
at System.Data.Mapping.Update.Internal.UpdateTranslator.BackPropagateServerGen(List`1 generatedValues)
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Objects.ObjectContext.SaveChanges()
之前,一切都运行良好。一旦我这样做,保存我修改后的实体:
exec sp_executesql N'update [dbo].[UsersView]
set [UserName] = @0, [LastName] = @1, [FirstName] = @2, [MiddleName] = @3, [Suffix] = null, [Pid] = @4, [IsLoggedIn] = @5, [DisplayName] = @10
where ([Id] = @12)
select [ComputedProperty]
from [dbo].[UsersView]
where @@ROWCOUNT > 0 and [Id] = @12',N'@0 nvarchar(35),@1 nvarchar(35),@2 nvarchar(35),@3 nvarchar(35),@4 nvarchar(4),@5 bit,@6 bit,@7 bit,@8 nvarchar(max) ,@9 nvarchar(max) ,@10 nvarchar(max) ,@11 int,@12 int',@0=N'yaya',......
我没有更改Id的值。事实上,如果我根本不更改ANYTHING并且只是重新连接到第二个ObjectContext,设置Modified,并调用Save,我就可以重现这个错误。
我可以看到为更新生成的SQL反映出我已将此属性设置为computed:
{{1}}
同样,在我将ComputedProperty设置为StoreGeneratedPattern为Computed之前,一切都运行正常,没有任何问题。看起来这必须与上面添加到更新SQL的附加SELECT语句有关...因为异常发生在更新SQL已经执行之后。
这里有什么问题?
感谢。
答案 0 :(得分:1)
将对象状态条目的状态设置为modified将导致将每个属性设置为已修改。相反,您应该只标记明确修改的属性,如本答案中所示。 Entity framework 4, update specific properties
答案 1 :(得分:0)
嗯,我想你可以称之为我自己的愚蠢,但这种行为有点不直观。
如果其他人实现INSTEAD OF触发器以通过EF启用可更新视图,则应注意此处描述的实现:error when inserting into table having instead of trigger from entity data framework应该仅用于INSTEAD OF INSERT触发器,而不是INSTEAD OF UPDATE触发器。将SELECT添加到而不是更新触发器的末尾将导致问题中描述的异常。