C# - Can’t map HERITAGE with Entity Framework Core - Code First?

Asked

Viewed 892 times

0

I’m not able to map the Person and Client classes (Table Per Type (TPT) using the Entity Framework Core), Customer inherits from Person.

How do I do?

public class Pessoa
{
    public int PessoaId { get; set; }
}


public class Cliente : Pessoa
{
}

public DbSet<Pessoa> Pessoa { get; set; }
public DbSet<Cliente> Cliente { get; set; }

public void PessoaMapping(ModelBuilder modelBuilder)
{
       modelBuilder.Entity<Pessoa>()
                .ToTable("tblPessoa");

       modelBuilder.Entity<Pessoa>()
                .HasKey(p => p.PessoaId);

       modelBuilder.Entity<Pessoa>()
                .Property(p => .PessoaId).ValueGeneratedNever();
}

public void ClienteMapping(ModelBuilder modelBuilder)
{
      modelBuilder.Entity<Cliente>()
             .ToTable("tblCliente");
}

1 answer

0


Created classes is only set in context in the method OnModelCreating or even by Dataannotations, this minimum example is configured by the method OnModelCreating:

public class Pessoa
{
    public int PessoaId { get; set; }
    public string Nome { get; set; }
}

public class Cliente: Pessoa
{
    public string CPF { get; set; }
}

using Microsoft.EntityFrameworkCore;

public class Ctx: DbContext
{
    public Ctx()
    {
        //Database.EnsureCreated();
    }

    public DbSet<Pessoa> Pessoa { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {            
        string cn = "Server=.\\SQLExpress;Database=MyDataBaseEntityCore;";
        cn += "User Id=sa;Password=senha;";

        optionsBuilder.UseSqlServer(cn, c =>
        {

        });
    }

    //configurando as classes
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {

        modelBuilder.Entity<Pessoa>()
            .ToTable("Pessoa")
            .ForSqlServerToTable("Pessoa")
            .HasKey(x => x.PessoaId);

        modelBuilder.Entity<Pessoa>()
            .Property(x => x.PessoaId)
            .IsRequired()
            .UseSqlServerIdentityColumn();

        modelBuilder.Entity<Pessoa>()
            .Property(x => x.Nome)
            .HasMaxLength(100)
            .IsRequired();


        modelBuilder.Entity<Cliente>()
            .ForSqlServerToTable("Cliente")
            .ToTable("Cliente");

        modelBuilder.Entity<Cliente>()
            .Property(x => x.CPF)
            .IsRequired()
            .HasMaxLength(20);

    }
}

One point to note is that this version (1.1.2) of the Entity Framework Core, even configuring the tables, does not generate a table for each type (as requested in the question), but a field Discriminator to identify to which type that record belongs, I believe to be a limitation still of the version.

Remarks: Just remembering that this setting is for Entity Framework Core 1.1.2 to the bank SQLServer, this being the most stable, but, is in the oven almost ready version 2.0.0, that will bring many changes.

Operations:

  • Add new Cliente:

    using (Ctx c = new Ctx())
    {
        c.Pessoa.Add(new Cliente
        {
            CPF = "111.111.111-11",
            Nome = "StackOverFlow Core"
        });
        c.SaveChanges();
    }
    
  • Edit Cliente of PessoaId = 1:

    using (Ctx c = new Ctx())
    {
         Cliente cliente = c.Pessoa
            .OfType<Cliente>()
            .FirstOrDefault(x => x.PessoaId == 1);
    
        if (cliente != null)
        {
            cliente.Nome = "StackOverFlow Core + Update";
            c.SaveChanges();
        }    
    }
    
  • Rule out Cliente of PessoaId = 1:

    using (Ctx c = new Ctx())
    {
        Cliente cliente = c.Pessoa
            .OfType<Cliente>()
            .FirstOrDefault(x => x.PessoaId == 1);
        if (cliente != null)
        {
            c.Pessoa.Remove(cliente);
            c.SaveChanges();
        }                
    }
    
  • Fetch Cliente of PessoaId = 2:

    using (Ctx c = new Ctx())
    {
        Cliente cliente = c.Pessoa
            .OfType<Cliente>()
            .FirstOrDefault(x => x.PessoaId == 2);
        if (cliente != null)
        {
    
        }                
    }
    

References

  • 1

    Thanks Virgilio Novic. I tried everything but it didn’t work. Unfortunately, as you said, it should still be a limitation of the version. I will wait... :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.