Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add-Migration fails with "An item with the same key has already been added" when renaming entity #27504

Closed
srmagura opened this issue Feb 24, 2022 · 30 comments
Labels
area-migrations closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. Servicing-approved type-bug
Milestone

Comments

@srmagura
Copy link

I made this change to my DbContext and now Add-Migration fails:

-        public DbSet<DbImport> Imports => Set<DbImport>();
+        public DbSet<DbPageImport> PageImports => Set<DbPageImport>();

In words: I renamed the DbImport entity class AND renamed the Imports table.

Include your code

I have tried to create a minimal reproduction of the issue but can't get the error to occur. If necessary, I can strip out everything from my real codebase until I have a small project that demonstrates the bug (but this would be a lot of work).

Both me and my coworker are able to consistently reproduce the bug on our real closed-source codebase. I am happy to send this codebase to any EF Core contributor as a private GitHub repo.

Include verbose output

Output from Add-Migration in Package Manager Console in Visual Studio 2022:

PM> add-migration TestMigration -Verbose
Using project 'Backend\Data\DataContext'.
Using startup project 'Backend\Functions\FunctionApp'.
Build started...
Build succeeded.
C:\Program Files\dotnet\dotnet.exe exec --depsfile C:\Projects\System7\Slateplan\Backend\Functions\FunctionApp\bin\Debug\net6.0\FunctionApp.deps.json --additionalprobingpath C:\Users\SamMa\.nuget\packages --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig C:\Projects\System7\Slateplan\Backend\Functions\FunctionApp\bin\Debug\net6.0\FunctionApp.runtimeconfig.json C:\Users\SamMa\.nuget\packages\microsoft.entityframeworkcore.tools\6.0.2\tools\netcoreapp2.0\any\ef.dll migrations add TestMigration --json --verbose --no-color --prefix-output --assembly C:\Projects\System7\Slateplan\Backend\Functions\FunctionApp\bin\Debug\net6.0\DataContext.dll --project C:\Projects\System7\Slateplan\Backend\Data\DataContext\DataContext.csproj --startup-assembly C:\Projects\System7\Slateplan\Backend\Functions\FunctionApp\bin\Debug\net6.0\FunctionApp.dll --startup-project C:\Projects\System7\Slateplan\Backend\Functions\FunctionApp\FunctionApp.csproj --project-dir C:\Projects\System7\Slateplan\Backend\Data\DataContext\ --language C# --configuration Debug --working-dir C:\Projects\System7\Slateplan --root-namespace DataContext --nullable
Using assembly 'DataContext'.
Using startup assembly 'FunctionApp'.
Using application base 'C:\Projects\System7\Slateplan\Backend\Functions\FunctionApp\bin\Debug\net6.0'.
Using working directory 'C:\Projects\System7\Slateplan\Backend\Functions\FunctionApp'.
Using root namespace 'DataContext'.
Using project directory 'C:\Projects\System7\Slateplan\Backend\Data\DataContext\'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'FunctionApp'...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'AppDataContext'.
Using context 'AppDataContext'.
Finding design-time services referenced by assembly 'FunctionApp'...
Finding design-time services referenced by assembly 'DataContext'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding IDesignTimeServices implementations in assembly 'FunctionApp'...
No design-time services were found.
The index {'OrganizationId'} was not created on entity type 'DbComponentType' as the properties are already covered by the index {'OrganizationId', 'Name'}.
The index {'ComponentId'} was not created on entity type 'DbComponentVersion' as the properties are already covered by the index {'ComponentId', 'VersionName'}.
The index {'PageId'} was not created on entity type 'DbDesignerData' as the properties are already covered by the index {'PageId', 'Type'}.
The index {'OrganizationId'} was not created on entity type 'DbLogoSet' as the properties are already covered by the index {'OrganizationId', 'Name'}.
The index {'OrganizationId'} was not created on entity type 'DbProductFamily' as the properties are already covered by the index {'OrganizationId', 'Name'}.
The index {'ProductKitId'} was not created on entity type 'DbProductKitVersion' as the properties are already covered by the index {'ProductKitId', 'VersionName'}.
The index {'OrganizationId'} was not created on entity type 'DbProductPhoto' as the properties are already covered by the index {'OrganizationId', 'Name'}.
The index {'OrganizationId'} was not created on entity type 'DbProject' as the properties are already covered by the index {'OrganizationId', 'Name'}.
The index {'ProjectId'} was not created on entity type 'DbProjectPublication' as the properties are already covered by the index {'ProjectId', 'RevisionNumber'}.
The index {'OrganizationId'} was not created on entity type 'DbSymbol' as the properties are already covered by the index {'OrganizationId', 'Name'}.
The index {'OrganizationId'} was not created on entity type 'DbTermsDocument' as the properties are already covered by the index {'OrganizationId', 'Number'}.
The property 'DbComponentVersion.SellPrice#Money.DbComponentVersionId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbComponentVersion.Url#Url.DbComponentVersionId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbLogoSet.DarkLogo#DbFileRef.DbLogoSetId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbLogoSet.LightLogo#DbFileRef.DbLogoSetId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbPage.Pdf#DbFileRef.DbPageId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbPage.Thumbnail#DbFileRef.DbPageId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbPageImport.File#DbFileRef.DbPageImportId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbPageImport.PercentComplete#Percentage.DbPageImportId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbProductKitVersion.SellPrice#Money.DbProductKitVersionId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbProductPhoto.Photo#DbFileRef.DbProductPhotoId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbProject.Photo#DbFileRef.DbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbReport.File#DbFileRef.DbReportId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbReport.PercentComplete#Percentage.DbReportId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbTermsDocument.File#DbFileRef.DbTermsDocumentId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbUser.Email#EmailAddress.DbUserId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'DbProjectReportOptions.DbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'EncodedPassword.DbUserId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'PhoneNumber.CompanyContactInfoDbProjectReportOptionsDbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'CompanyContactInfo.DbProjectReportOptionsDbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'CompanyContactInfo.Email#EmailAddress.CompanyContactInfoDbProjectReportOptionsDbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'CompanyContactInfo.Url#Url.CompanyContactInfoDbProjectReportOptionsDbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'OrganizationShortName.DbOrganizationId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'PartialAddress.DbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'PersonName.DbUserId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'PostalCode.PartialAddressDbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'ProjectBudgetOptions.DbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'ProjectBudgetOptions.CostAdjustment#Percentage.ProjectBudgetOptionsDbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
The property 'ProjectBudgetOptions.DepositPercentage#Percentage.ProjectBudgetOptionsDbProjectId' was created in shadow state because there are no eligible CLR members with a matching name.
DetectChanges starting for 'AppDataContext'.
DetectChanges completed for 'AppDataContext'.
DetectChanges starting for 'AppDataContext'.
DetectChanges completed for 'AppDataContext'.
'AppDataContext' disposed.
System.ArgumentException: An item with the same key has already been added. Key: System.Object Item [System.String]
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedProperties(IEntityType entityType, ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedColumns(ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Add(ITable target, DiffContext diffContext)+MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffCollection[T](IEnumerable`1 sources, IEnumerable`1 targets, DiffContext diffContext, Func`4 diff, Func`3 add, Func`3 remove, Func`4[] predicates)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDifferences(IRelationalModel source, IRelationalModel target)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
An item with the same key has already been added. Key: System.Object Item [System.String]

Include provider and version information

EF Core version: 6.0.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.1.0

@srmagura
Copy link
Author

Workaround

  1. Rename the entity class: DbImport -> DbPageImport.
  2. Add migration.
  3. Rename the DbSet property on the DbContext: Imports -> PageImports
  4. Add migration. (it works)

@ajcvickers
Copy link
Member

@bricelam I think we might have seen this before.

@bricelam
Copy link
Contributor

Looks like #26405, but that was supposed to be fixed in 6.0.2.

@ajcvickers
Copy link
Member

@srmagura I think we're going to need a full repro for this.

@srmagura
Copy link
Author

srmagura commented Mar 2, 2022

@ajcvickers No problem. Are you all right with me sending the full project (with repro instructions), or should I work on trimming out everything that is not relevant to the bug?

@ajcvickers
Copy link
Member

@srmagura The latter is always preferred. Assuming there is a bug here, then that work will have to be done by someone, and it's often easier for the person who knows the code than it is for someone like me who has to figure out how everything in the project is organized and fits together.

@srmagura
Copy link
Author

srmagura commented Mar 2, 2022

Sounds good, I will work on it. It may be about 2 weeks — I'll comment here when it is ready.

@glenkitchen
Copy link

@srmagura upgrading to 6.0.2 as per @bricelam above,
fixed issue for me

@srmagura
Copy link
Author

Minimal repro is done! https://github.com/srmagura/EFIssue27504 The README includes instructions for reproducing the bug. Thank you.

@mjamro
Copy link

mjamro commented May 2, 2022

@srmagura upgrading to 6.0.2 as per @bricelam above, fixed issue for me

Is it fixed on 6.0.2? I'm still getting it on 6.0.4

   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedProperties(IEntityType entityType, ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedColumns(ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Add(ITable target, DiffContext diffContext)+MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffCollection[T](IEnumerable`1 sources, IEnumerable`1 targets, DiffContext diffContext, Func`4 diff, Func`3 add, Func`3 remove, Func`4[] predicates)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDifferences(IRelationalModel source, IRelationalModel target)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
An item with the same key has already been added. Key: System.Object Item [System.String]
Entity Framework Core .NET Command-line Tools
6.0.4

@AndriySvyryd
Copy link
Member

@mjamro Make sure to update all EF packages, not just the tools

@eMTeeSK
Copy link

eMTeeSK commented Jul 25, 2022

Hello,
I am getting same error, when I try to create migration after removing entity with owned entities.
Version of all EFCore related nugets + tools: 6.0.7
In this example project EfMigrationIssueOwnedEntities.zip you can get error by using commands:
When I try to add migration either by dotnet ef migrations add DroFoo or Add-Migration DropFoo in package manager console, i am getting same error:

Build started...
Build succeeded.
System.ArgumentException: An item with the same key has already been added. Key: System.Object Item [System.String]
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedProperties(IEntityType entityType, ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedColumns(ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Add(ITable target, DiffContext diffContext)+MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffCollection[T](IEnumerable`1 sources, IEnumerable`1 targets, DiffContext diffContext, Func`4 diff, Func`3 add, Func`3 remove, Func`4[] predicates)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDifferences(IRelationalModel source, IRelationalModel target)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.De
[EfMigrationIssueOwnedEntities.zip](https://github.com/dotnet/efcore/files/9182842/EfMigrationIssueOwnedEntities.zip)
[EfMigrationIssueOwnedEntities.zip](https://github.com/dotnet/efcore/files/9182856/EfMigrationIssueOwnedEntities.zip)
sign.OperationExecutor.OperationBase.Execute(Action action)
An item with the same key has already been added. Key: System.Object Item [System.String]

There is workaround:

  1. Flatten entity: replace owned entities with direct properties. Column names and types remains same
  2. Create intermediate migration - it should be empty
  3. Remove entity and entity configuration
  4. Create migration - it should contain drop table command
  5. You can remove intermediate migration

@huang-tianwen
Copy link

I just got this error after doing major code refactoring.
The scenario is There was AgentBooking Entity.
Now the business decide to add OnlineBooking, Then I need to refactor AgentBooking & OnlineBooking to inherit from Abstract Booking Entity and rename some columns.

This error appear, if I remove all previous migrations & DbContextModelSnapshot, then recreate one it will be successful.
But there is no way to run this migration in production environment.

Is there anyway to debug migrations tools? I need to find out where is the problem.
Key: System.Object Item [System.String] is kinda unhelpful at all.

@ajcvickers ajcvickers added the punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. label Sep 16, 2022
@ajcvickers ajcvickers modified the milestones: 7.0.0, Backlog Sep 16, 2022
@carlosrfernandez
Copy link

Got the same when adding a migration that removes two completely independent DbSets (flat tables no relationships etc).

@nev-21
Copy link

nev-21 commented Oct 27, 2022

I got the same error, I'm using entities with owned entities.
If I remove the DbSets the generated migrations are empty.
If I remove the DbSets and fluent-maps, it throw the error.

@wojtek-viirtue
Copy link

Seeing the same in 6.0.1 caused by removing an entity (and the associated DbSet on the DbContext) that had an owned entity.

I was able to work around this by removing the representation of said entity in the snapshot, scaffolding an empty migration and populating the respective Up and Down from the initial migration that was already present.

System.ArgumentException: An item with the same key has already been added. Key: System.Object Item [System.String]
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedProperties(IEntityType entityType, ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedProperties(IEntityType entityType, ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedColumns(ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Add(ITable target, DiffContext diffContext)+MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffCollection[T](IEnumerable`1 sources, IEnumerable`1 targets, DiffContext diffContext, Func`4 diff, Func`3 add, Func`3 remove, Func`4[] predicates)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDifferences(IRelationalModel source, IRelationalModel target)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
An item with the same key has already been added. Key: System.Object Item [System.String]

@lakeman
Copy link

lakeman commented Nov 25, 2022

+1..
In my use case I'm trying to write my own version of EnsureCreatedAsync using either the IMigrationsAssembly.ModelSnapshot.Model or migration.TargetModel, so I can then test further migrations;

var migrations = db.GetService<IMigrationsAssembly>();
var init = db.GetService<IModelRuntimeInitializer>();
var model = migrations.ModelSnapshot.Model;
if (model is IMutableModel m)
    model = m.FinalizeModel();
model = init.Initialize(model);
var relational = model.GetRelationalModel();
var diffOperations = modelDiffer.GetDifferences(null, relational);

However at

groups.Add(linkingNavigationProperty, properties);
linkingNavigationProperty is always the same PropertyInfo; Dictionary<string,object>.Item[string]. Leading to the same duplicate key exception as seen above.

MigrationsModelDiffer.GetSortedProperties is clearly assuming that all PropertyInfo's are unique. Which is an invalid assumption.

Perhaps this dummy PropertyInfo should not be set in the relational model, or it should be treated the same as a null value in the loop linked above.

@lakeman
Copy link

lakeman commented Nov 25, 2022

Adding an explicit test for Dictionary<string,object> should fix the problem;

foreach (var linkingForeignKey in table.GetReferencingRowInternalForeignKeys(entityType))
{
    var linkingNavigationProperty = linkingForeignKey.PrincipalToDependent?.PropertyInfo;
    var properties = GetSortedProperties(linkingForeignKey.DeclaringEntityType, table).ToList();
    if (linkingNavigationProperty == null
+       || linkingNavigationProperty.DeclaringType == typeof(Dictionary<string,object>))
    {
        leastPriorityProperties.AddRange(properties);
        continue;
    }

Or should that be something like;

foreach (var linkingForeignKey in table.GetReferencingRowInternalForeignKeys(entityType))
{
    var properties = GetSortedProperties(linkingForeignKey.DeclaringEntityType, table).ToList();
    var linkingNavigation = linkingForeignKey.PrincipalToDependent;
    if (linkingNavigation?.PropertyInfo == null
        || linkingNavigation.IsIndexerProperty()
        || linkingNavigation.IsShadowProperty())
    {
        leastPriorityProperties.AddRange(properties);
        continue;
    }
    var linkingNavigationProperty = linkingNavigation.PropertyInfo;

    groups.Add(linkingNavigationProperty, properties);

@HugCoder
Copy link

Hi there! Anything happening on this bug? I just did a big refactor on my project, both dropping (empty) and adding tables, incl. owned-properties. I'm using .net6 and tried EF Core Tools 6.0.12 and now even 7.0.1 (still using .net6).

System.ArgumentException: An item with the same key has already been added. Key: System.Object Item [System.String]
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedProperties(IEntityType entityType, ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedColumns(ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Add(ITable target, DiffContext diffContext)+MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffCollection[T](IEnumerable`1 sources, IEnumerable`1 targets, DiffContext diffContext, Func`4 diff, Func`3 add, Func`3 remove, Func`4[] predicates)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDifferences(IRelationalModel source, IRelationalModel target)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

This should probably rank as one of the most useless error messages I have seen, so I really don't know what to do. Considering recreating the entire database right now as I was just suppose to clean up and publish this...

Best regards,

@amosolson
Copy link

This just hit us on a large project that has recently been upgraded to .net7 and EF Core 7.01. We are refactoring to remove all OwnedEntities. We removed one, successfully added a migration, then spent hours factoring out dozens of other owned entites. Then we tried to add another migration and this error hit.

The error is so vague it gives no clue how to proceed.

System.ArgumentException: An item with the same key has already been added. Key: System.Object Item [System.String]
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedProperties(IEntityType entityType, ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedColumns(ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Add(ITable target, DiffContext diffContext)+MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffCollection[T](IEnumerable`1 sources, IEnumerable`1 targets, DiffContext diffContext, Func`4 diff, Func`3 add, Func`3 remove, Func`4[] predicates)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDifferences(IRelationalModel source, IRelationalModel target)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

@lakeman
Copy link

lakeman commented Dec 30, 2022

This bug is triggered while sorting columns for a create table operation. When two classes map to the same table, via a navigation property that is also an "indexer property".

When loading a model snapshot, all properties are indexer properties. So this bug is most likely triggered when the model differ can't locate a matching table in your new model, and needs to generate a create table operation for the Down script.

You could try scaffolding your schema in a blank project. Adding a migration. Then moving the contents of the generated model snapshot to your code first project. Avoiding any shared tables in the model snapshot.

@lakeman
Copy link

lakeman commented Dec 30, 2022

The one line diff I posted above should avoid the exception. But a better fix would sort columns without using PropertyInfo as a dictionary key.

For my own project I replaced the model differ service to test the one line code change. However, overriding the implementation of MigrationsModelDiffer.GetSortedProperties involved copying huge slabs of internal code. Not really viable as a workaround for production code. Though you only need this fix when generating migrations, you don't need to deploy any of this code to production.

@pklejnowski
Copy link

pklejnowski commented Jan 4, 2023

This just hit us on a large project that has recently been upgraded to .net7 and EF Core 7.01. We are refactoring to remove all OwnedEntities. We removed one, successfully added a migration, then spent hours factoring out dozens of other owned entites. Then we tried to add another migration and this error hit.

The error is so vague it gives no clue how to proceed.

System.ArgumentException: An item with the same key has already been added. Key: System.Object Item [System.String]
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedProperties(IEntityType entityType, ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetSortedColumns(ITable table)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Add(ITable target, DiffContext diffContext)+MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffCollection[T](IEnumerable`1 sources, IEnumerable`1 targets, DiffContext diffContext, Func`4 diff, Func`3 add, Func`3 remove, Func`4[] predicates)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDifferences(IRelationalModel source, IRelationalModel target)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

It happened to me too after upgrade following packages:

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.1" />

Now I cannot create any Migration because of this error, so I had to downgrade these packages.

@Matt-Crow
Copy link

My error, and how I resolved it

I encountered the same error message when using Entity Framework Core .NET Command-line Tools 7.0.1 in a project that depended on versions 6.0.9 of each of the various Entity Framework Core packages. This is an oversimplification of my model, but it shows all the parts that were relevant to solving my error.

Code

DbContext snippet

public DbSet<Foo> Foos { get; set; } = null!;

protected override void OnModelCreating(ModelBuilder mb)
{
    mb.Entity<Foo>().OwnsOne(f => f.Prop1);
    mb.Entity<Foo>().OwnsOne(f => f.Prop2);
}

Foo snippet

[Key]
public int FooId { get; set; }
public Bar Prop1 { get; set; } = new();
public Bar Prop2 { get; set; } = new();

Bar snippet

public string Baz { get; set; } = "";
public string Qux { get; set; } = "";

The problem

Removing the Foo class and any references to it and then running dotnet ef migrations add MigrationName resulted in the same error message as reported by others in this thread.

How I resolved it

  1. remove the navigation properties Prop1 and Prop2 from Foo
  2. add a new migration
  3. delete the DbSet<Foo> property from the DbContext
  4. add a new migration

Conclusion

I am relatively new to Entity Framework Core, so I cannot diagnose what initially caused this error, but I assume it has something to do with deleting entities that have owned entities attached.

@AndriySvyryd AndriySvyryd removed this from the Backlog milestone Jan 5, 2023
@ajcvickers ajcvickers added this to the 7.0.3 milestone Jan 5, 2023
@ajcvickers ajcvickers added Servicing-approved closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. labels Jan 5, 2023
@adampaquette
Copy link

@AndriySvyryd I just tested the latest dotnet ef cli, that I think should contain the fixe #29981, and I still get the error.

PS C:\Users\apaquette> dotnet tool uninstall -g dotnet-ef
L'outil 'dotnet-ef' (version '7.0.2') a été désinstallé.
PS C:\Users\apaquette> dotnet tool install -g dotnet-ef --version 8.0.0-* --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json
Vous pouvez appeler l'outil à l'aide de la commande suivante : dotnet-ef
L'outil 'dotnet-ef' (version '8.0.0-alpha.1.23066.4') a été installé correctement.

I have a table that contains owned types and this table is not registered with a DbSet<> but only by a IEntityTypeConfiguration<>. When removing the configuration I get the same error as everybody.

Was it supposed to work or is it the same message for an other error?
Thank you!

@ajcvickers
Copy link
Member

@adampaquette This fix is not included in 7.0.2. Check the milestone on the issue.

@adampaquette
Copy link

adampaquette commented Jan 17, 2023

@ajcvickers This is why I installed 8.0.0-alpha.1.23066.4. Hum

@ajcvickers
Copy link
Member

Ah sorry, missed that. The version of the CLI tool doesn't usually matter. Make sure your project is using the latest daily build packages.

@Sebazzz
Copy link

Sebazzz commented Jan 19, 2023

@ajcvickers We're also running into this issue when changing (and renaming) a 1:n entity to an owned entity. The workaround of ignoring unfortunately does not work. It appears that there are no pre-releases of EF 7.0.3 on the NuGet feed, is that observation correct?

edit: Unfortunately EF 8.0.0 alpha has the same issue. Happy to send the solution.

@ajcvickers
Copy link
Member

@Sebazzz Please open a new issue and attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate.

GodVenn added a commit to GodVenn/flotilla that referenced this issue Mar 21, 2023
Needed to purge migrations and database due to bug:
dotnet/efcore#27504
GodVenn added a commit to equinor/flotilla that referenced this issue Mar 21, 2023
Needed to purge migrations and database due to bug:
dotnet/efcore#27504
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-migrations closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported punted-for-7.0 Originally planned for the EF Core 7.0 (EF7) release, but moved out due to resource constraints. Servicing-approved type-bug
Projects
None yet
Development

No branches or pull requests