Pular para o conteúdo principal

Herança em classes de entidades

Temos uma classe Funcionario que herda de PessoaFisica. Quando a propriedade Cpf pertence à PessoaFisica, o EF Core entende que a configuração "mestra" dessa coluna deve vir da base.

Para resolver isso e declarar o índice na classe derivada (ou referenciando-a) sem conflitos, a melhor abordagem é utilizar a Fluent API dentro do seu DbContext.

A Solução com Fluent API

O segredo é configurar o índice diretamente no modelBuilder apontando para a classe Funcionario. O EF Core permite que você defina índices em classes derivadas, mesmo que a propriedade venha da base, desde que você não tente "reconfigurar" a propriedade em si (como mudar o nome da coluna ou o tipo) dentro do contexto da herança de forma conflitante.

No seu DbContext, faça o seguinte:

C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // Configure a herança (Exemplo usando TPH - Tabela Única)
    modelBuilder.Entity<PessoaFisica>()
        .HasDiscriminator<string>("TipoPessoa");

    // Configura o índice especificamente para Funcionario
    modelBuilder.Entity<Funcionario>()
        .HasIndex(f => f.Cpf)
        .IsUnique(false); // Define como não único
}

Por que o erro acontece?

Se você estiver usando IEntityTypeConfiguration<Funcionario>, o erro pode aparecer se você tentar fazer algo como builder.Property(x => x.Cpf)... antes de definir o índice. O EF Core impede que você configure propriedades da base dentro do builder da derivada para evitar inconsistências no mapeamento da tabela.

Ao chamar .HasIndex(f => f.Cpf) diretamente, você está dizendo ao EF: "Eu sei que Cpf existe, eu só quero colocar um índice nele para este tipo de entidade".

Entendendo o Impacto no Banco de Dados

A forma como esse índice será criado no banco depende da sua estratégia de herança (TPH, TPT ou TPC).

  • TPH (Table Per Hierarchy - Padrão): Se todos estiverem na mesma tabela, o índice será criado na tabela única. Se você quer que o CPF seja não único apenas para funcionários, mas único para outros, você precisará de um Filtro de Índice (Filtered Index).

  • TPT (Table Per Type): Se cada classe tiver sua própria tabela, o índice será criado na tabela de Funcionarios (se o campo estiver lá) ou na de PessoasFisicas.

Dica Pro: Índice Filtrado

Se você usa a estratégia de tabela única (TPH) e quer que o Cpf não seja único para Funcionario, mas seja único para o resto (como Cliente), você pode usar um filtro:

C#
modelBuilder.Entity<PessoaFisica>()
    .HasIndex(p => p.Cpf)
    .HasFilter("[Cpf] IS NOT NULL AND [TipoPessoa] <> 'Funcionario'")
    .IsUnique();

Isso garante a integridade dos dados para as outras classes enquanto permite a flexibilidade que você precisa para Funcionario.

Comentários

Postagens mais visitadas deste blog

UML e comunicação entre Componentes

(conteúdo gerado com I.A.) Antes de abordarmos o conceito de Componentes, vale a pena analisar como um programador iniciante costuma estruturar uma aplicação. Geralmente, a escolha é construir um monólito tradicional, agrupando todas as classes de domínio (como Categoria, Produto, Compra, Venda, Pagamento, etc.) em uma única pasta de Entidades. Da mesma forma, criam-se pacotes globais para Repositórios, Serviços e Controllers. O grande problema dessa abordagem é que ela gera um forte acoplamento entre as classes e as camadas do sistema. À medida que a aplicação cresce, isso desencadeia uma série de dificuldades: Manutenção e modelagem complexas: As responsabilidades se misturam. Rapidamente, o código passa a ter diversos trechos onde as classes assumem funções que não deveriam ter, tornando a evolução do sistema confusa. Escalabilidade ineficiente: Para escalar o backend, é necessário replicar a aplicação inteira e todo o banco de dados. Além de consumir mais recursos, isso traz o ri...

Quando escolher Flask ou Quart no Python

Atualmente , considerando o suporte assíncrono já presente no Flask, a escolha entre Flask e Quart para uma API Server depende de vários fatores técnicos. Vejamos alguns critérios: Fonte:  https://pt.stackoverflow.com/questions/51268/qual-a-diferen%C3%A7a-entre-comunica%C3%A7%C3%A3o-ass%C3%ADncrona-e-s%C3%ADncrona Suporte Assíncrono : Flask : O Flask oferece suporte assíncrono por meio de extensões de terceiros, como  flask[async] . No entanto, seu desempenho assíncrono é inferior aos frameworks nativamente assíncronos. Quart : O Quart é uma reimplantação do Flask baseada no padrão ASGI (Asynchronous Server Gateway Interface). Ele utiliza E/S assíncrona em todo o código e é mais adequado para bases de código predominantemente assíncronas. Desempenho : Flask : Como aplicação WSGI, o Flask usa um único worker para cada ciclo de solicitação/resposta. Quando uma solicitação chega a uma visualização assíncrona, o Flask inicia um loop de eventos em uma thread, executa a função da vi...

Metodo para criar relacionamento entre tabelas sem dar erro cíclico EFCore

Quando estamos modelando o banco de dados no Entity Framework Core (ou em qualquer outra ferramenta) é muito comum criarmos o erro cíclico. Este erro ocorre devido ao banco de dados não conseguir determinar onde o relacionamento termina, causando um erro de loop. Vejamos uma situação real onde foi gerado esse problema: Um Professor leciona em várias Turmas, Um Professor leciona uma ou mais Disciplinas, Um Professor leciona determinadas Disciplinas em determinadas Turmas, Uma Turma tem muitos Professores, Em todas as Turmas tem 9 Disciplinas. Em todas as turmas podem ter até 9 Professores. Só por essa descrição já é possível perceber que os relacionamentos podem ser complexos de entender. E tem-se também o problema da navegação em via dupla: Professor-Turmas, Turma-Professores. Então, como modelar essas tabelas sem que o banco entre em loop? Para resolver esse problema no Entity Framework Core e evitar o erro de "Multiple Cascade Paths" (caminhos múltiplos de cascata) comum n...