Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core 3: CLR property 'Number' cannot be added to entity type 'CHSIMTBase' because it is declared on the CLR type 'Contract'

I need to create a relationship between two classes ContractItem and Contract based on a contract number.

This relationship:

  1. targets a derived class Contract
  2. does not use Contract 's principal Key named Reference but Number

When using HasPrincipalKey( c => c.Number) on the relationship Contract-ContractIem, an error tells CLR property 'Number' cannot be added to entity type 'CHSIMTBase'.

But Contract is a derived class of abstract base class CHSIMTBase.

I could not find a way to create the relationship between Contract and ContractItem.

I tried to move the property Number on CHSIMTBase but

  • the CHSIMTBase is not a Contract
  • CHSIMTBase is abstract (there is no discriminator for this type )

Steps to reproduce

Here is the model and the context to reproduce the error:


    public abstract class CHSIMTBase
    {
        public int Reference { get; set; }
        public string ContractKey { get; set; }
    }

    public class Contract : CHSIMTBase
    {
        public string Number { get; set; }
        public virtual List<CustomerContractLink> CustomerContractLinkRef { get; set; }
    }

    public class CustomerContractLink : EntityLink
    {
        public int Reference { get; set; }
        public Contract Contract { get; set; }
        // public Customer Customer { get; set; }
    }

    public class ContractItem
    {
        public int Code { get; set; }
        public string ContractNumber { get; set; }
        public Contract Contract { get; set; }
       // public Service Service { get; set; }
    }

    public class CoherisContext : DbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<CHSIMTBase>(entity =>
            {
                entity.HasKey(e => e.Reference);
                entity.ToTable("CLIENTS");

                entity
                    .HasDiscriminator(e => e.EntityCode)
                    .HasValue<Customer>( (int) EntityCodes.Customer )
                    .HasValue<Site>(     (int) EntityCodes.Site )
                    .HasValue<Partner>(  (int) EntityCodes.Partner )
                    .HasValue<Contract>( (int) EntityCodes.Contract );

                entity.Property(e => e.Reference)            .HasColumnName("REFERENCE");

            });

            modelBuilder.Entity<Contract>(entity =>
            {
                entity.HasBaseType<CHSIMTBase>();

                entity
                    .HasMany( e => e.CustomerContractLinkRef )
                    .WithOne(c => c.Contract )

                // entity
                //     .HasMany(e => e.ContractItems)
                //     .WithOne(i => i.Contract)
                //     .HasPrincipalKey(i => i.ContractKey)
                //     .HasForeignKey(i => i.ContractNumber);
                //     
                entity.Property(e => e.Number)        .HasColumnName("CL_RUB1");
            });


            modelBuilder.Entity<ContractItem>(entity =>
            {
                entity.ToTable("AF_LINK");
                entity.HasKey(e => e.Code);
                entity.Property(e => e.Code) .HasColumnName("AF_CODE");
                entity.Property(e => e.ContractNumber) .HasColumnName("AF_INFO_COMP1");

                // generate error CLR property 'Number' cannot be added to entity type 'CHSIMTBase' because it is declared on the CLR type 'Contract'.
                entity.HasOne( e => e.Contract)
                    .WithMany().HasPrincipalKey( c => c.Number).HasForeignKey( e => e.ContractNumber );
            });
        }
    }

Further technical details

EF Core version: 3.1.6 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET Core 3.0 Operating system: Windows 10 IDE: Visual Studio 2019

like image 764
Anthony Brenelière Avatar asked Dec 05 '25 14:12

Anthony Brenelière


1 Answers

EF Core 3.1 version does not support using an alternative key as foreign key in a relationship, if that mapped alternative key is part of a derived class ( https://github.com/dotnet/efcore/issues/21974 ).

For the entity Contract, the principal key is Reference and the alternative key used in the relationship with ContractItem is Number.

So the solution was to move the alternative key's property Number from the derived class Contract to the base class CHSIMTBase.

The downside is that property is accessible to all derived classes. If another propery of a derived class is mapped on the same column, then a common name must be chosen to match both properties (or use derived well-named properties that point to that property shared in the base class).

like image 69
Anthony Brenelière Avatar answered Dec 08 '25 07:12

Anthony Brenelière



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!