Задать вопрос
Timur2342
@Timur2342

Как сделать Table Per Class и почему у меня вылетает ошибка «A key cannot be configured on 'CustomerEntity' because it is a derived type. »?

Проблема в том что получаю непонятно почему(для меня) ошибку: "System.InvalidOperationException: A key cannot be configured on 'CustomerEntity' because it is a derived type. The key must be configured on the root type 'UserEntity'. If you did not intend for 'UserEntity' to be included in the model, ensure that it is not referenced by a DbSet property on your context, referenced in a configuration call to ModelBuilder, or referenced from a navigation on a type that is included in the model.". Не совсем могу понять что от меня хотят. Понял лишь что то то не так с ключем, хотя вроде все норм. Буду очень благодарен за любой ответ.

Базовые сущности:
public abstract class UserEntity : Entity
{
    public string Name { get; set; }
    public string Email { get; set; }
    public bool EmailVerify { get; set; }
    public string PasswordHash { get; set; }
}
public abstract class Entity
{
    public Guid Id { get; set; } = Guid.NewGuid();
}


Дочерние сущности:
public class CustomerEntity : UserEntity
{
    public List<ProductEntity> Purchases { get; set; }
    public string CreditCard { get; set; }
        
    public static CustomerEntity? Create(string name, string email, string passwordHash)
    {
        var customer = new CustomerEntity
        {
            Name = name,
            Email = email,
            PasswordHash = passwordHash,
            EmailVerify = false
        };

        if (CustomerValidator.IsValid(customer))
            return customer;

        return null;
    }
    public static CustomerEntity? Create(UserRegistrationQuery dto, string passwordHash) => Create(dto.Name, dto.Email, passwordHash);
}
public class SellerEntity : UserEntity
{
    public string Description { get; set; }
    public List<ProductEntity> Products { get; set; }

    public static SellerEntity? Create(string name, string email, string passwordHash)
    {
        var seller = new SellerEntity
        {
            Name = name,
            Email = email,
            PasswordHash = passwordHash,
            EmailVerify = false
        };

        return SellerValidator.IsValid(seller) ? seller : null;
    }

    public static SellerEntity? Create(UserRegistrationQuery dto, string passwordHash) =>
        Create(dto.Name, dto.Email, passwordHash);
}


Конфиги:
public class CustomerEntityConfiguration : IEntityTypeConfiguration<CustomerEntity>
{
    public void Configure(EntityTypeBuilder<CustomerEntity> builder)
    {
        builder.UseTpcMappingStrategy();
        builder.HasKey(x => x.Id).HasName("id");
        builder.Property(x => x.Name).HasMaxLength(25).IsRequired().HasColumnName("name");
        builder.Property(x => x.Email).HasMaxLength(50).IsRequired().HasColumnName("email");
        builder.Property(x => x.EmailVerify).IsRequired().HasColumnName("email_verify");
        builder.Property(x => x.PasswordHash).IsRequired().HasColumnName("password_hash");
        builder.ToTable("customers");

        builder.Property(x => x.CreditCard).IsRequired().HasMaxLength(35).HasColumnName("credit_card");
        builder.HasMany(x => x.Purchases)
            .WithOne().HasConstraintName("purchases_constraint");
    }
}

public class SellerEntityConfiguration : IEntityTypeConfiguration<SellerEntity>
{
    public void Configure(EntityTypeBuilder<SellerEntity> builder)
    {
        builder.UseTpcMappingStrategy();
        
        builder.HasKey(x => x.Id).HasName("id");
        builder.Property(x => x.Name).HasMaxLength(25).IsRequired().HasColumnName("name");
        builder.Property(x => x.Email).HasMaxLength(50).IsRequired().HasColumnName("email");
        builder.Property(x => x.EmailVerify).IsRequired().HasColumnName("email_verify");
        builder.Property(x => x.PasswordHash).IsRequired().HasColumnName("password_hash");      
        builder.ToTable("sellers");
        
        builder.Property(x => x.Description).IsRequired().HasMaxLength(500).HasColumnName("description");
        builder.HasMany(x => x.Products).WithOne().HasConstraintName("products_constraint");
    }
}

DbContext(смотреть особо нечего)
public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(IConfiguration conf,
        ILogger<ApplicationDbContext> logger)
    {
        Database.EnsureDeleted();
        Database.EnsureCreated();

        _logger = logger;
        _pgConnectionStr = conf["UserSecrets:PostgresConnectionStr"];

        if (_pgConnectionStr == null)
            throw new NullReferenceException("No PostgresConnectionStr"); 
    }

    public DbSet<CustomerEntity> Customers { get; set; } = null;
    public DbSet<SellerEntity> Sellers { get; set; } = null;
    public DbSet<RefreshTokenEntity> RefreshTokens { get; set; } = null;
    public DbSet<ProductEntity> Products { get; set; } = null;
    public DbSet<DeliveryCompanyEntity> DeliveryCompanies { get; set; } = null;
    public DbSet<ImageEntity> Images { get; set; } = null;

    private readonly string _pgConnectionStr;
    private readonly ILogger<ApplicationDbContext> _logger;

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseNpgsql(_pgConnectionStr)
            .UseLoggerFactory(CreateLoggerFactory())
            .EnableSensitiveDataLogging();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new DeliveryCompanyEntityConfiguration());
        modelBuilder.ApplyConfiguration(new RefreshTokenEntityConfigurations());
        modelBuilder.ApplyConfiguration(new CustomerEntityConfiguration());
        modelBuilder.ApplyConfiguration(new SellerEntityConfiguration());
        modelBuilder.ApplyConfiguration(new ProductEntityCongurations());
    }

    private ILoggerFactory CreateLoggerFactory() => LoggerFactory.Create(conf => { conf.AddConsole(); });
}


  • Вопрос задан
  • 54 просмотра
Подписаться 1 Средний Комментировать
Решения вопроса 1
Geminix
@Geminix
Фуллстек nuxt, .net разработчик
Полагаю, что useTpcMapping надо применить к конфигурации UserEntity
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы