【问题标题】:The property 'Id' is part of the object's key information and cannot be modified ON SELECT属性“Id”是对象的关键信息的一部分,不能在 SELECT 上修改
【发布时间】:2015-10-01 09:18:52
【问题描述】:

我们在应用程序中的特定查询中遇到此错误的概率约为 3 次:

The property 'Id' is part of the object's key information and cannot be modified.

at System.Data.Entity.Core.Objects.EntityEntry.VerifyEntityValueIsEditable(StateManagerTypeMetadata typeMetadata, Int32 ordinal, String memberName)
at System.Data.Entity.Core.Objects.EntityEntry.GetAndValidateChangeMemberInfo(String entityMemberName, Object complexObject, String complexObjectMemberName, StateManagerTypeMetadata& typeMetadata, String& changingMemberName, Object& changingObject)
at System.Data.Entity.Core.Objects.EntityEntry.EntityMemberChanging(String entityMemberName, Object complexObject, String complexObjectMemberName)
at System.Data.Entity.Core.Objects.EntityEntry.EntityMemberChanging(String entityMemberName)
at System.Data.Entity.Core.Objects.ObjectStateEntry.System.Data.Entity.Core.Objects.DataClasses.IEntityChangeTracker.EntityMemberChanging(String entityMemberName)
at System.Data.Entity.Core.Objects.Internal.SnapshotChangeTrackingStrategy.SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, Int32 ordinal, Object target, Object value)
at System.Data.Entity.Core.Objects.Internal.EntityWrapper`1.SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, Int32 ordinal, Object target, Object value)
at System.Data.Entity.Core.Objects.DataClasses.EntityReference.UpdateForeignKeyValues(IEntityWrapper dependentEntity, IEntityWrapper principalEntity, Dictionary`2 changedFKs, Boolean forceChange)
at System.Data.Entity.Core.Objects.DataClasses.EntityReference.UpdateDependentEndForeignKey(RelatedEnd targetRelatedEnd, Boolean forceForeignKeyChanges)
at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedTarget, Boolean applyConstraints, Boolean addRelationshipAsUnchanged, Boolean relationshipAlreadyExists, Boolean allowModifyingOtherEndOfRelationship, Boolean forceForeignKeyChanges)
at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedEntity, Boolean applyConstraints)
at System.Data.Entity.Core.Objects.DataClasses.EntityReference`1.set_ReferenceValue(IEntityWrapper value)
at System.Data.Entity.Core.Objects.DataClasses.EntityReference.SetEntityKey(EntityKey value, Boolean forceFixup)
at System.Data.Entity.Core.Objects.EntityEntry.FixupEntityReferenceToPrincipal(EntityReference relatedEnd, EntityKey foreignKey, Boolean setIsLoaded, Boolean replaceExistingRef)
at System.Data.Entity.Core.Objects.EntityEntry.FixupReferencesByForeignKeys(Boolean replaceAddedRefs, EntitySetBase restrictTo)
at System.Data.Entity.Core.Objects.ObjectStateManager.FixupReferencesByForeignKeys(EntityEntry newEntry, Boolean replaceAddedRefs)
at System.Data.Entity.Core.Objects.ObjectStateManager.AddEntry(IEntityWrapper wrappedObject, EntityKey passedKey, EntitySet entitySet, String argumentName, Boolean isAdded)
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.HandleEntity[TEntity](IEntityWrapper wrappedEntity, EntityKey entityKey, EntitySet entitySet)
at lambda_method(Closure , Shaper )
at System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper)
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.RowNestedResultEnumerator.MaterializeRow()
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.RowNestedResultEnumerator.MoveNext()
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.TryReadToNextElement()
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.ReadElement()
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.ObjectQueryNestedEnumerator.MoveNext()
at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
....project specific stack elements

有问题的查询是简单的选择查询:

var set = ObjectContext.CreateObjectSet<TModel>();
set = set.WithMergeOption(MergeOption.OverwriteChanges)
var results = set.Where(p => (!p.IsArchived && !p.IsDeleted))
    .Include(w => w.CurrentPlaceStructure)
    .Include(o => o.Room.Wing.Location)
    .Include(r => r.Residencies)
    .Include(r => r.PlaceStructures)
    .Include(r => r.Room.RoomStructures)
    .ToList();

错误信息&谷歌提示尝试修改Id值时会出现此错误。然而,这只是一个选择语句,我们不会修改此查询中的任何内容。请注意,在此之前其他查询已在 DbContext 上运行,因此其他对象可能已经在上下文中。

为什么会在 select 语句中出现这种情况?

为什么它只会出现大约每 3 次中的 1 次?

哪些复合因素可能导致此错误消息?

【问题讨论】:

  • 报告错误的地方可能不会发生错误。当您在每个方法中都没有异常处理程序(try/catch)时,就会发生有趣的事情。当发生异常时,编译后的代码会向上移动执行堆栈,直到找到第一个异常处理程序。 Linq 内置了异常处理程序。因此,在执行此代码之前就发生了错误。找到真正改变 id 的代码。
  • 谢谢,我在异常中看到的堆栈跟踪与引发的断点匹配,所以我相信它发生在指定的位置。在执行 ToList() 查询时,它似乎发生在 Entity Framework 内部。

标签: c# entity-framework linq-to-entities invalidoperationexception entity-framework-6.1


【解决方案1】:

我找到了原因。

事实证明,在多个线程中同时使用了相同的 DbContext。 EF6 对于这种用法不是线程安全的,因此会发生随机内部错误。

【讨论】:

    猜你喜欢
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    相关资源
    最近更新 更多