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

Error when setting column attributes #30118

Closed
r-work opened this issue Jan 23, 2023 · 3 comments
Closed

Error when setting column attributes #30118

r-work opened this issue Jan 23, 2023 · 3 comments

Comments

@r-work
Copy link

r-work commented Jan 23, 2023

Not sure how to explain the issue, but I can demonstrate two scenarios where it works with one but not the other, so here it goes (or check the repro repo:

Scenario 1

If we create a table like the following (note that column names are PascalCase):

CREATE TABLE IF NOT EXISTS public."GenericTable1"
(
    "Id" bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
    "TypeId" bigint,
    "Content" text COLLATE pg_catalog."default",
    CONSTRAINT generic_table1_pkey PRIMARY KEY ("Id")
)

And have a bit of code like the following

    public class MyDbContext1 : DbContext
    {
        public DbSet<GenericTable1> T1 { get; set; }
        public DbSet<GenericTable1<GenericTableData1>> T2 { get; set; }
        public DbSet<GenericTable1<GenericTableData2>> T3 { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseNpgsql("Server=localhost;Port=5432;Database=testdb;User Id=postgres;Password=123456");

            base.OnConfiguring(optionsBuilder);
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<GenericTable1>().HasKey(x => x.Id);
            modelBuilder.Entity<GenericTable1>().HasDiscriminator(x => x.TypeId).HasValue(-1);

            modelBuilder.Entity<GenericTable1<GenericTableData1>>().HasDiscriminator(x => x.TypeId).HasValue(1);
            modelBuilder.Entity<GenericTable1<GenericTableData2>>().HasDiscriminator(x => x.TypeId).HasValue(2);

            modelBuilder.Entity<GenericTable1<GenericTableData1>>().Property(x => x.Content).HasColumnType("jsonb");
            modelBuilder.Entity<GenericTable1<GenericTableData2>>().Property(x => x.Content).HasColumnType("jsonb");

            base.OnModelCreating(modelBuilder);
        }
    }

    [Table("GenericTable1")]
    public class GenericTable1
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long Id { get; set; }

        public long TypeId { get; set; }
    }

    public class GenericTable1<T> : GenericTable1
    {
        public T Content { get; set; }
    }

And to run the above, works fine without any issues:

//this works
using (var context = new MyDbContext1())
{
     var data = context.T2.Where(x => x.Id > 0).ToList();
}

Scenario 2

Now if we create another table, pretty much the same as before (note that column names are snake_case):

CREATE TABLE IF NOT EXISTS public.generic_table2
(
    id bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
    type_id bigint,
    content text COLLATE pg_catalog."default",
    CONSTRAINT generic_table2_pkey PRIMARY KEY (id)
)

And the code (note the 'Column' attributes:

    public class MyDbContext2 : DbContext
    {
        public DbSet<GenericTable2> T1 { get; set; }
        public DbSet<GenericTable2<GenericTableData1>> T2 { get; set; }
        public DbSet<GenericTable2<GenericTableData2>> T3 { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseNpgsql("Server=localhost;Port=5432;Database=testdb;User Id=postgres;Password=123456");

            base.OnConfiguring(optionsBuilder);
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<GenericTable2>().HasKey(x => x.Id);
            modelBuilder.Entity<GenericTable2>().HasDiscriminator(x => x.TypeId).HasValue(-1);

            modelBuilder.Entity<GenericTable2<GenericTableData1>>().HasDiscriminator(x => x.TypeId).HasValue(1);
            modelBuilder.Entity<GenericTable2<GenericTableData2>>().HasDiscriminator(x => x.TypeId).HasValue(2);

            modelBuilder.Entity<GenericTable2<GenericTableData1>>().Property(x => x.Content).HasColumnType("jsonb");
            modelBuilder.Entity<GenericTable2<GenericTableData2>>().Property(x => x.Content).HasColumnType("jsonb");

            base.OnModelCreating(modelBuilder);
        }
    }

    [Table("generic_table2")]
    public class GenericTable2
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Column("id")]
        public long Id { get; set; }

        [Column("type_id")]
        public long TypeId { get; set; }
    }

    public class GenericTable2<T> : GenericTable2
    {
        [Column("content")]
        public T Content { get; set; }
    }

And to run it:

//this doesn't work
using (var context = new MyDbContext2())
{
      var data = context.T2.Where(x => x.Id > 0).ToList();
}

It throws:
'GenericTable2<GenericTableData1>.Content' and 'GenericTable2<GenericTableData2>.Content' are both mapped to column 'content' in 'generic_table', but are configured to use differing provider types ('GenericTableData1' and 'GenericTableData2').

Stack trace

   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateCompatible(IProperty property, IProperty duplicateProperty, String columnName, StoreObjectIdentifier& storeObject, IDiagnosticsLogger`1 logger)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.NpgsqlModelValidator.ValidateCompatible(IProperty property, IProperty duplicateProperty, String columnName, StoreObjectIdentifier& storeObject, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateSharedColumnsCompatibility(IReadOnlyList`1 mappedTypes, StoreObjectIdentifier& storeObject, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateSharedTableCompatibility(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.NpgsqlModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel(Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__8_4(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_ContextServices()
   at Microsoft.EntityFrameworkCore.DbContext.get_Model()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.CheckState()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider()
   at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)
   at EfTest.Program.Main(String[] args) in C:\Users\rebin\source\repos\EfTest\EfTest\Program.cs:line 16

Repro repo:

https://github.com/r-work/EfTest

Include provider and version information

EF Core version: 7.0.2
Database provider: Npgsql.EntityFrameworkCore.PostgreSQL v7.0.1
Target framework: .NET 7.0
Operating system: Windows 11 22H2 (22621.1105)
IDE: Visual Studio 2022 17.5 Preview 3.0

This works if I downgrade to EntityFrameworkCore 6.0.13 and PostgreSQL 6.0.8

@SEmadH
Copy link

SEmadH commented Jan 24, 2023

Scenario 2 in OnModelCreating add:
modelBuilder.Entity<GenericTable2>().ToTable("generic_table2"); modelBuilder.Entity<GenericTable2>().Property(p => p.Id).HasColumnName("id"); modelBuilder.Entity<GenericTable2>().Property(p => p.TypeId).HasColumnName("type_id");

@r-work
Copy link
Author

r-work commented Jan 24, 2023

Scenario 2 in OnModelCreating add: modelBuilder.Entity<GenericTable2>().ToTable("generic_table2"); modelBuilder.Entity<GenericTable2>().Property(p => p.Id).HasColumnName("id"); modelBuilder.Entity<GenericTable2>().Property(p => p.TypeId).HasColumnName("type_id");

Done that, throws the same exception.

@ajcvickers
Copy link
Contributor

Probably a duplicate of #29859.

/cc @AndriySvyryd @roji

@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Jan 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants