question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Scaffold error when two indexes exist on the same column set

See original GitHub issue

In https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/228, @berets76 describes an issue with the way indices are managed during scaffolding.

PostgreSQL supports multiple index “methods”, and the Npgsql provider represents these via a simple string annotation on the index - all indices in a scaffolded DatabaseModel contain this annotation (note that if the default method is detected, the annotation is later eliminated by convention in NpgsqlAnnotationCodeGenerator).

Now, consider the following database schema:

CREATE TABLE data
(
  id integer PRIMARY KEY,
  name character(3)
);

CREATE INDEX index1 ON data (name);
CREATE INDEX index2 ON data (name DESC);

Two indices exist on the same column, which should be fine. However, trying to scaffold this throws the following:

System.InvalidOperationException: The annotation 'Npgsql:IndexMethod' cannot be added because an annotation with the same name already exists.
   at Microsoft.EntityFrameworkCore.Infrastructure.Annotatable.AddAnnotation(String name, Annotation annotation)
   at Microsoft.EntityFrameworkCore.MutableAnnotatableExtensions.AddAnnotations(IMutableAnnotatable annotatable, IEnumerable`1 annotations)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitIndex(EntityTypeBuilder builder, DatabaseIndex index) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Scaffolding\Internal\RelationalScaffoldingModelFactory.cs:line 607
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitIndexes(EntityTypeBuilder builder, ICollection`1 indexes) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Scaffolding\Internal\RelationalScaffoldingModelFactory.cs:line 560
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitTable(ModelBuilder modelBuilder, DatabaseTable table) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Scaffolding\Internal\RelationalScaffoldingModelFactory.cs:line 323
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitTables(ModelBuilder modelBuilder, ICollection`1 tables) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Scaffolding\Internal\RelationalScaffoldingModelFactory.cs:line 279
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitDatabaseModel(ModelBuilder modelBuilder, DatabaseModel databaseModel) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Scaffolding\Internal\RelationalScaffoldingModelFactory.cs:line 182
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.Create(DatabaseModel databaseModel, Boolean useDatabaseNames) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Scaffolding\Internal\RelationalScaffoldingModelFactory.cs:line 99
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.ReverseEngineerScaffolder.ScaffoldModel(String connectionString, IEnumerable`1 tables, IEnumerable`1 schemas, String namespace, String language, String contextDir, String contextName, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Scaffolding\Internal\ReverseEngineerScaffolder.cs:line 97
   at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String outputContextDir, String dbContextClassName, IEnumerable`1 schemas, IEnumerable`1 tables, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Design\Internal\DatabaseOperations.cs:line 94
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String outputDbContextDir, String dbContextClassName, IEnumerable`1 schemaFilters, IEnumerable`1 tableFilters, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Design\OperationExecutor.cs:line 463
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_1.<.ctor>b__0() in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Design\OperationExecutor.cs:line 445
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0() in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Design\OperationExecutor.cs:line 555
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action) in C:\b\w\33bdfc1cae7b2a38\modules\EntityFrameworkCore\src\EFCore.Design\Design\OperationExecutor.cs:line 538

It seems that at some point during the scaffolding process, the two indices provided by the DatabaseModel get “collapsed” to one, and we get the error since the annotation is already set. This is probably because at some point EF Core looks up the index, keying only by the column list, and omits other index characteristics (e.g ascending/descending).

Thanks again to @berets76 for reproducing and analyzing, I only provided the writeup.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:5
  • Comments:23 (19 by maintainers)

github_iconTop GitHub Comments

1reaction
AndriySvyrydcommented, Sep 1, 2020

Named indexes are now supported, so this can be fixed properly

1reaction
rojicommented, May 27, 2018

@divega an index on tolower() in PostgreSQL would be an expression index. There is no specific support for those in the Npgsql provider (see https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/119) but they can be created with raw SQL.

To summarize, I think there are several legitimate reasons why someone would have multiple indices on the same column set; between expression indices, ASC/DESC, index methods (a concept specific to PostgreSQL) I think there’s enough material. At the moment, when scaffolding EF Core will retain the last index present on the database model, and silently discard the others.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Scaffold error when two indexes exist on the same column ...
The indices are individually named, but get collapsed/keyed into one single index builder, that throws once the annotation gets set the second ...
Read more >
Entity Framework Core Problem with Scaffolding ...
After trying to make it work with the existing database => and fail, the only solution is add key to both tables (principal...
Read more >
Find tables with multiple indexes on same column
My problem is when a table has 2 different index with the same column (one ASC and one DESC ); I am trying...
Read more >
Scaffolding (Reverse Engineering) - EF Core
Reverse engineering a model from an existing database using Entity Framework Core.
Read more >
- Create index on single column got 3519 error - Community
I'm using SQL Assistant 7.2 and Teradata database V2R6.2 on Windows Server 2003, sp2. ... "3519: Two indexes with the same columns".
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found