2012-01-02 83 views
4

我有一個在實體框架映射更新視圖(EDMX設計師)實體框架4.0不起作用使用計算性能

一切工作都很好,直到我添加屬性我更新的視圖(和實體)標有StoreGeneratedPatternComputed。一旦我這樣做,保存我的修改後的實體:

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() 

我還沒有更改Id的值。事實上,如果我根本不改變任何東西,只需重新附加到第二個ObjectContext,設置Modified,然後調用Save,就可以重現此錯誤。

我可以看到更新生成的SQL反映,我已經設置該屬性爲計算:

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',...... 

再次,一切完美,沒有任何問題,直到我設置ComputedProperty到已經計算的StoreGeneratedPattern。看起來這似乎與添加到上面的更新SQL中的額外SELECT語句有關......因爲在已執行SQL更新之後發生異常。

這裏有什麼問題?

謝謝。

+0

你是什麼意思的可更新視圖,你是如何映射它。這在您使用表格時毫無問題。 – 2012-01-02 08:44:06

+0

我的意思是我有一個SQL Server視圖,而不是定義插入,更新和刪除觸發器。我在這裏使用的方法來解決scope_identity問題:http://stackoverflow.com/questions/5820992/error-when-inserting-into-table-having-instead-of-trigger-from-entity-data-frame – Jeff 2012-01-02 18:36:15

+0

我不知道如果我的更新觸發器在最後一行中有相同的「select id ...」,並且如果這使得它以某種方式搞砸了......將立即回發... – Jeff 2012-01-02 18:37:49

回答

1

將對象狀態條目的狀態設置爲已修改將導致將每個屬性設置爲已修改。相反,您應該只標記顯式修改的屬性,如此答案中所示。 Entity framework 4, update specific properties

+1

設置修改狀態只會影響「 StoreGeneratedPattern'設置爲'None'。 'StoreGeneratedPattern'設置爲'Identity'或'Computed'的屬性不應該受到影響。 – 2012-01-02 08:42:07

0

嗯,我想你可以稱之爲我自己的愚蠢,但這種行爲有點不直觀。

如果其他人實現了INSTEAD OF觸發器以通過EF啓用可更新視圖,應該注意這裏描述的實現:error when inserting into table having instead of trigger from entity data framework應該只用於INSTEAD OF INSERT觸發器,而不是INSTEAD OF UPDATE觸發器。將SELECT添加到更新觸發器的末尾將導致問題中描述的異常。