You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using Entity Framework 6 (Database-First approach), an attempt to save a set of modified entities derived from the same base class failed with "System.ArgumentException: Object must be of type Int32." The entities in question were implemented using the Table-Per-Type (TPT) inheritance strategy, and the derived types happened to have the same number of "key-identifier" fields (as outlined in more detail below...).
Based on what I've observed, there appears to be a limitation / bug in the framework within the EF code responsible for determining the order in which to produce/execute the database commands. I tried version 6.1.3 and 6.2, both with the same results.
The following is the Exception I received...
Exception message: System.ArgumentException: Object must be of type Int32 Stack trace:
at System.Int32.CompareTo(Object value)
at System.Collections.Comparer.Compare(Object a, Object b)
at System.Collections.Generic.ObjectComparer`1.Compare(T x, T y)
at System.Collections.Generic.Comparer`1.System.Collections.IComparer.Compare(Object x, Object y)
at System.Data.Entity.Core.Common.Utils.ByValueComparer.System.Collections.IComparer.Compare(Object x, Object y)
at System.Data.Entity.Core.Mapping.Update.Internal.**FunctionUpdateCommand.CompareToType**(UpdateCommand otherCommand)
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateCommand.CompareTo(UpdateCommand other)
at System.Collections.Generic.GenericComparer`1.Compare(T x, T y)
at System.Collections.Generic.SortedSet`1.AddIfNotPresent(T item)
at System.Data.Entity.Core.Mapping.Update.Internal.Graph`1.TryTopologicalSort(IEnumerable`1& orderedVertices, IEnumerable`1& remainder)
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.ProduceCommands()
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update()
at System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.<Update>b__2(UpdateTranslator ut)
at System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update[T](T noChangesResult, Func`2 updateFunction)
at System.Data.Entity.Core.EntityClient.Internal.EntityAdapter.Update()
at System.Data.Entity.Core.Objects.ObjectContext.<SaveChangesToStore>b__35()
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction)
at System.Data.Entity.Core.Objects.ObjectContext.<>c__DisplayClass2a.<SaveChangesInternal>b__27()
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction)
at System.Data.Entity.Core.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at Rodan.EMIS.ObjectModel.Core.Repository.GenericEFUnitOfWork.SaveChanges(OperationLog opLog, Boolean throwOnError)
at Rodan.EMIS.Configuration.Core.FieldServices.SaveChangesToDatabase(DataProviderUnitOfWork dataProviderUoW, OperationLog opLog, MergeOptions options)
at Rodan.EMIS.Configuration.Core.EMISConfiguration.SaveToDatabase(MergeOptions options)
at Rodan.EMIS.Configuration.Core.EMISConfiguration.ImportConfiguration(String sourceXmlFilePath, MergeOptions dbMergeOptions, String optClientNameFilter, String operationLogXmlFilePath)
at Rodan.EMIS.Configuration.Core.Tests.EMISConfigurationTests.ImportConfiguration_successfullyImportsThenModifiesNewClientFromXml2DB()
Steps to reproduce (sort of)
When breaking on the exception, and examining the call-stack at the function highlighted above, I found the following...
The System.ArgumentException occurred when EF was (presumably) trying to establish what order to issue the DB commands in
The FunctionUpdateCommand.CompareToType() comparison function:
was comparing a “DataSource” update command with a “DataPoint” update command (meaning both were in the “Modified” state)
correctly detected that both objects/commands were directed to the same repository (i.e. “IntegrationNodes”)
correctly detected that both objects/commands had the same number of “identifiers” (i.e. 8)
incorrectly attempted to compare each identifier assuming they were of the same type
although the entities shared the same base type, the Entity Types were in fact different (DataSource vs. DataPoint) as noted above
the corresponding key identifiers (and their types), were also different (see image below).
specifically, the exception occurred while attempting to compare the DataPoint's "dataRepresentationID" (type Int32) with the DataSource's "ownerVisibilityScopeID" (type Byte)
Based on my understanding (albeit limited) of the issue here, I made the following change to the System.Data.Entity.Core.Mapping.Update.Internal.FunctionUpdateCommand.CompareToType function:
From
…
// order by key valuesvarthisInputIdentifierCount=(null==_inputIdentifiers?0: _inputIdentifiers.Count);varotherInputIdentifierCount=(null== other._inputIdentifiers ?0: other._inputIdentifiers.Count);result=thisInputIdentifierCount-otherInputIdentifierCount;if(0!=result){returnresult;}for(vari=0;i<thisInputIdentifierCount;i++){varthisParameter= _inputIdentifiers[i].Value;varotherParameter= other._inputIdentifiers[i].Value;result= ByValueComparer.Default.Compare(thisParameter.Value, otherParameter.Value);if(0!=result){returnresult;}}
…
To:
…
// order by key value countvarthisInputIdentifierCount=(null==_inputIdentifiers?0: _inputIdentifiers.Count);varotherInputIdentifierCount=(null== other._inputIdentifiers ?0: other._inputIdentifiers.Count);result=thisInputIdentifierCount-otherInputIdentifierCount;if(0!=result){returnresult;}// order by key types/valuesfor(vari=0;i<thisInputIdentifierCount;i++){varthisParameter= _inputIdentifiers[i].Value;varotherParameter= other._inputIdentifiers[i].Value;// order by key typesresult=(int)thisParameter.DbType -(int)otherParameter.DbType;if(0!=result){returnresult;}// order by key valuesresult= ByValueComparer.Default.Compare(thisParameter.Value, otherParameter.Value);if(0!=result){returnresult;}}
…
The above changes addressed the issue I was having, and the SQL commands were subsequently successfully generated and executed by the framework.
Does this fix make sense, and, if so, could it be incorporated into the official version? We're otherwise working with the official (6.2) version.
Further technical details
EF version: 6.13, 6.2
Database Provider: EntityFramework.SqlServer
Operating system: Windows 7
IDE: Visual Studio 2015 (14.0 Update 3)
The text was updated successfully, but these errors were encountered:
brian-vn
added a commit
to brian-vn/EntityFramework6
that referenced
this issue
Oct 24, 2018
This issue has been closed because EF6 is no longer being actively developed. We are instead focusing on stability of the codebase, which means we will only make changes to address security issues. See the repo README for more information.
Using Entity Framework 6 (Database-First approach), an attempt to save a set of modified entities derived from the same base class failed with "System.ArgumentException: Object must be of type Int32." The entities in question were implemented using the Table-Per-Type (TPT) inheritance strategy, and the derived types happened to have the same number of "key-identifier" fields (as outlined in more detail below...).
Based on what I've observed, there appears to be a limitation / bug in the framework within the EF code responsible for determining the order in which to produce/execute the database commands. I tried version 6.1.3 and 6.2, both with the same results.
The following is the Exception I received...
Exception message: System.ArgumentException: Object must be of type Int32
Stack trace:
Steps to reproduce (sort of)
When breaking on the exception, and examining the call-stack at the function highlighted above, I found the following...
Based on my understanding (albeit limited) of the issue here, I made the following change to the System.Data.Entity.Core.Mapping.Update.Internal.FunctionUpdateCommand.CompareToType function:
The above changes addressed the issue I was having, and the SQL commands were subsequently successfully generated and executed by the framework.
Does this fix make sense, and, if so, could it be incorporated into the official version? We're otherwise working with the official (6.2) version.
Further technical details
EF version: 6.13, 6.2
Database Provider: EntityFramework.SqlServer
Operating system: Windows 7
IDE: Visual Studio 2015 (14.0 Update 3)
The text was updated successfully, but these errors were encountered: