Efcore.pg: Gist exclude constraint breaks scaffolding

Created on 6 May 2018  路  14Comments  路  Source: npgsql/efcore.pg

When scaffolding my schema i get an error unless i exclude my gist constraints.

offending table with foreign keys removed:

CREATE TABLE price (
  id_price      INTEGER GENERATED ALWAYS AS IDENTITY
    CONSTRAINT pk_price
    PRIMARY KEY,
  campaign_rate INT     NOT NULL                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     DEFAULT 0 C
  from_date     date,
  to_date       date,
  value         NUMERIC NOT NULL,
  CONSTRAINT unique_price_per_period EXCLUDE USING gist (campaign_rate WITH =, daterange(from_date, to_date, '[)') WITH &&)
);

Error message:

System.ArgumentException: The collection argument 'propertyNames' must contain at least one element.
   at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty[T](IReadOnlyList`1 value, String parameterName)
   at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.HasIndex(String[] propertyNames)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitIndex(EntityTypeBuilder builder, DatabaseIndex index)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitIndexes(EntityTypeBuilder builder, ICollection`1 indexes)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitTable(ModelBuilder modelBuilder, DatabaseTable table)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitTables(ModelBuilder modelBuilder, ICollection`1 tables)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitDatabaseModel(ModelBuilder modelBuilder, DatabaseModel databaseModel)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.Create(DatabaseModel databaseModel, Boolean useDatabaseNames)
   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)
   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)
   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)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_1.<.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)
The collection argument 'propertyNames' must contain at least one element.

Most helpful comment

In the meantime you can clone https://github.com/roji/Npgsql.EntityFrameworkCore.PostgreSQL/tree/rc and built that, the last (trivial) commit you see is the fix for the scaffolding issue.

All 14 comments

Can you please check the table definition above? On the campaign_rate there's an illegal DEFAULT 0 C after a lot of spaces, and PostgreSQL errors. Removing that and trying to create the table errors with:

ERROR:  data type integer has no default operator class for access method "gist"
HINT:  You must specify an operator class for the index or define a default operator class for the data type.

I tested with a more standard example of an exclusion constraint and everything scaffolded fine (the exclusion part isn't scaffolded because it isn't currently supported):

CREATE TABLE circles (
    id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    c circle,
    EXCLUDE USING gist (c WITH &&)
);

Sorry @roji lost a bit of text when copying and pasting from Visual studio.. some text was thrown about a meter to the right when pasted, corrections broke stuff.
Here is a proper sample:

CREATE TABLE testtable (
  id_testtable      INTEGER GENERATED ALWAYS AS IDENTITY
    CONSTRAINT pk_testtable
    PRIMARY KEY,
  fr_item       INT     NOT NULL,
  fr_actor      INT ,
  fr_currency   INT     NOT NULL,
  campaign_rate INT     NOT NULL                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     DEFAULT 0 CONSTRAINT check_campaign_rate_fake_bool CHECK (campaign_rate BETWEEN 0 AND 1),
  from_date     date,
  to_date       date,
  value         NUMERIC NOT NULL,
  CONSTRAINT unique_testtable_per_period EXCLUDE USING gist (daterange(from_date, to_date, '[)') WITH &&)
);

Migration through npgsql worked fine. Execution of the statement directly worked fine but when this constraint was in the database to be scaffolded the error above was given.

Might be the construction of the range that breaks it?

OK, I can see the issue happening and will investigate. I definitely don't think it's the date range, that's a purely PostgreSQL side concern that the client side is never exposed to.

Is there any way of skipping all constraint in the scaffolding function?

The cause of the issue was the presence of an expression index/constraint - regardless of whether it's an exclusion or not. Although expression indices aren't supported (#119), the scaffolded database model previously contained them for completeness (they were ignored). Apparently a change in EF Core itself caused this to become a problem, so the model no longer contains expression indices at all, and a warning is issued.

This should be released with rc1 very soon.

Thank you for a super speedy response. I love the PG community.

I have the same issue, I've tried with many combinations of Npgsql.EntityFrameworkCore.PostgreSQL (up to 2.1.0-preview2) and Microsoft.EntityFrameworkCore.Design (up to v2.1.0-rc1-final) and I still have this error.

Is there a quick workaround? I'm trying to scaffold an existing database that I'm taking over and I would be happy just with a partial result.

If I can help, just ask, I'll do my best.
Thanks!

@nockawa this fix will be released with Npgsql.EntityFrameworkCore.PostgreSQL 2.0.0-rc1, which isn't out yet but will be very very soon.

My quick fix until this is available as a proper patch was to find and temporarily remove the offending indexes in my database, scaffold and re-add them.

2.1.0-rc1 is out, give it a test to confirm that everything works.

@roji thanks for the prompt answer, unfortunately it now crash somewhere else...

With Microsoft.EntityFrameworkCore.Design v2.1.0-rc1-final

System.InvalidOperationException: Unable to resolve service for type 'Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.INpgsqlOptions' while attempting to activate 'Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlTypeMappingSource'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.CreateServiceAccessor(Type serviceType)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   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)
   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)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_1.<.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)
Unable to resolve service for type 'Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.INpgsqlOptions' while attempting to activate 'Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlTypeMappingSource'.

With M.EFC.D v2.0.3
System.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.IRelationalTypeMapper' while attempting to activate 'Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory'. at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.CreateServiceAccessor(Type serviceType) at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String dbContextClassName, IEnumerable`1 schemas, IEnumerable`1 tables, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String dbContextClassName, IEnumerable`1 schemaFilters, IEnumerable`1 tableFilters, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_1.<.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) Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Storage.IRelationalTypeMapper' while attempting to activate 'Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory'.

Which I found an issue from you on MS's repo, so I assume I should use the latest version of M.EFC.D?

Thanks

Damn, I did the rc1 release a bit too quickly - yeah, scaffolding is broken. The fix is very simple, but I'll wait a little before releasing rc1.1 with a fix for this.

Sorry about this...

@roji can you tell me how I can fix it? because I'm stuck if I can't scaffold.
thanks

In the meantime you can clone https://github.com/roji/Npgsql.EntityFrameworkCore.PostgreSQL/tree/rc and built that, the last (trivial) commit you see is the fix for the scaffolding issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fernandolguevara picture fernandolguevara  路  3Comments

roji picture roji  路  4Comments

Joseph-Anthony-King picture Joseph-Anthony-King  路  3Comments

roji picture roji  路  4Comments

Drago95 picture Drago95  路  3Comments