I need to create a relationship between two classes ContractItem and Contract based on a contract number.
This relationship:
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
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 );
});
}
}
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
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With