'The corresponding CLR type for entity type cannot be instantiated Table-per-type
Using EFCore 5
I've been trying to follow Microsoft tutorials to create a field in a model class that may reference two other classes.
In my case, I have an abstract Credentials class and two child classes: ClientCredentials and AccessKeyCredentials. There's an Organization class that holds a reference to Credentials and can use any of the child classes to instantiate the object.
I want so that there's a choice of what type of credentials to use.
However, I've came across an error:
System.InvalidOperationException: The corresponding CLR type for entity type 'Credentials' cannot be instantiated, and there is no derived entity type in the model that corresponds to a concrete CLR type.
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateClrInheritance(IModel model, IEntityType entityType, HashSet`1 validEntityTypes)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateClrInheritance(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.SqlServer.Internal.SqlServerModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.ValidatingConvention.ProcessModelFinalized(IModel model)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalized(IModel model)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalized(IModel model)
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
...
It's not really clear for me what is the issue here. I've been trying to follow a few documentation pages but didn't succeed.
Just in case, the links are:
- https://docs.microsoft.com/en-us/ef/core/modeling/inheritance
- https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt
Here is my code sample:
Credentials.cs
public abstract class Credentials
{
public Credentials()
{
this.CreatedOn = DateTime.Now;
}
[Key]
public Guid Id { get; set; }
public int TypeId { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
[ForeignKey("TypeId")]
public virtual CredentialsType Type { get; set; }
}
ClientCredentials.cs
public class ClientCredentials : Credentials
{
[Required]
public string ClientId { get; set; }
public string ClientSecret { get; set; }
}
AccessKeyCredentials.cs
public class AccessKeyCredentials : Credentials
{
[Required]
public string Username { get; set; }
public string AccessKey { get; set; }
}
Organization.cs
public class Organization
{
public Organization()
{
this.CreatedOn = DateTime.Now;
}
[Key]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
public string Country { get; set; }
public string City { get; set; }
public string Address { get; set; }
public string PhoneNumber { get; set; }
public string AdditionalInformation { get; set; }
public string BusinessCentralInstanceUrl { get; set; }
public Guid BusinessCentralCredentialsId { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public virtual IList<UserIdentity> Users { get; set; }
[ForeignKey("BusinessCentralCredentialsId")]
public virtual Credentials BusinessCentralCredentials { get; set; }
}
DbContext.cs
public class OrganizationDbContext : DbContext, IOrganizationDbContext
{
public DbSet<Organization> Organizations { get; set; }
public DbSet<Credentials> Credentials { get; set; }
public DbSet<CredentialsType> CredentialTypes { get; set; }
public OrganizationDbContext(DbContextOptions<OrganizationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Organization>(entity =>
{
entity.ToTable(TableConsts.Organizations);
entity.HasKey(x => x.Id);
entity.HasMany(x => x.Users)
.WithOne(x => x.Organization)
.OnDelete(DeleteBehavior.ClientSetNull);
//entity.HasOne(x => x.BusinessCentralCredentials)
// .WithOne()
// .OnDelete(DeleteBehavior.ClientSetNull);
});
//modelBuilder.Entity<Credentials>(entity =>
//{
// entity.ToTable(TableConsts.BusinessCentralCredentials);
// entity.HasKey(x => x.Id);
// entity.HasOne(x => x.Type)
// .WithOne()
// .OnDelete(DeleteBehavior.ClientSetNull);
//});
//modelBuilder.Entity<Credentials>().ToTable(TableConsts.BusinessCentralCredentials);
modelBuilder.Entity<ClientCredentials>().ToTable(TableConsts.BusinessCentralClientCredentials);
modelBuilder.Entity<AccessKeyCredentials>().ToTable(TableConsts.BusinessCentralAccessKeyCredentials);
modelBuilder.Entity<CredentialsType>(entity =>
{
entity.ToTable(TableConsts.BusinessCentralCredentialTypes);
entity.HasKey(x => x.Id);
});
modelBuilder.Entity<UserIdentity>()
.ToTable(TableConsts.AspNetUsers, t => t.ExcludeFromMigrations());
}
}
Hope you may help to find out some fix for this.
Thank you in advance.
UPD: I can create migration and apply it without any error. Error happens when I launch my app.
Solution 1:[1]
Remove "abstract" from class definition. I don't know why it is like that.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |