Inheritance Modeling MySQL and C #

5

I am having a question about modeling a DesktopApplication system in C # with MySQL.

Essentially I will have the Client, Supplier, PF and PJ entities. PF can be a customer or supplier. And PJ can also be a customer or supplier. My goal is to use Entity Framework and my biggest concern is with query performance, records listings and reports. I have seen several approaches and discussions about it, but nothing conclusive.

Anyway, I'm in doubt among the 3 modeling options below:

Option 1:

CLIENTE
-id_cliente

FORNECEDOR
-id_fornecedor

PF
-id_pf
-id_cliente (não obrigatório)
-id_fornecedor (não obrigatório)

PJ
-id_pj
-id_cliente (não obrigatório)
-id_fornecedor (não obrigatório)

Option 2:

CLIENTE
-id_cliente
-id_pj (não obrigatório)
-id_pf (não obrigatório)

FORNECEDOR
-id_fornecedor
-id_pj (não obrigatório)
-id_pf (não obrigatório)

PF
-id_pf

PJ
-id_pj

Option 3 (which I used to use):

CLIENTE
-id_cliente
-id_pessoa (obrigatório)
-tipo (para indicar se o id_pessoa é na tabela PF ou PJ)

FORNECEDOR
-id_fornecedor
-id_pessoa (obrigatório)
-tipo (para indicar se o id_pessoa é na tabela PF ou PJ)

PF
-id_pf

PJ
-id_pj

I do not know what the C # template looks like in this 3rd option. I know that at the bank only level, it would be more efficient, but what would the models look like in C #? I do not think he would understand this form.

Could anyone give guidance to resolve this impasse? If you can give examples of implementing queries for the best suggestion I will be immensely grateful!

Based on the excellent answers you gave me, I built the template as follows:

However,generatingthemodelslookslikethis:

[Table("pessoa")]
public partial class pessoa
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public pessoa()
    {
        cliente = new HashSet<cliente>();
        fornecedor = new HashSet<fornecedor>();
        pessoafisica = new HashSet<pessoafisica>();
        pessoajuridica = new HashSet<pessoajuridica>();
    }

    [Key]
    public int idPessoa { get; set; }

    [Required]
    [StringLength(90)]
    public string nomeRazaoSocial { get; set; }

    public bool pf { get; set; }

}



[Table("pessoafisica")]
public partial class pessoafisica
{
    [Key]
    public int idPessoaFisica { get; set; }

    [StringLength(15)]
    public string cpf { get; set; }

    public int idPessoa { get; set; }

    public virtual pessoa pessoa { get; set; }
}


[Table("pessoajuridica")]
public partial class pessoajuridica
{
    [Key]
    public int idPessoaJuridica { get; set; }

    [StringLength(45)]
    public string cnpj { get; set; }

    public int idPessoa { get; set; }

    public virtual pessoa pessoa { get; set; }
}

That is, there was no specialization at the code level.

Speaking in practical terms! If I want to put together a listing of all people, with the columns person_id, NameOrSocial, CPF / CNPJ.

In this case I would have to use if else to know if it is PF or PJ and to know if I search the information in the personal or personal object?

Is there any strategy in Entity so that the person object knows where it should get this information from?

What would be the high-level solution for this issue?

Once again thank you!

    
asked by anonymous 09.03.2016 / 20:24

2 answers

7

In this answer, I explain how make inheritance for Individuals and Legal .

With this, Cliente and Fornecedor would be compositions of a Pessoa . See that in the answer quoted I speak about inheritance and composition. So, the Models would look like this:

public class Cliente
{
    [Key, ForeignKey("Pessoa")]
    public int PessoaId { get; set; }

    // Coloque os demais campos aqui.

    public virtual Pessoa Pessoa { get; set; }
}

public class Fornecedor
{
    [Key, ForeignKey("Pessoa")]
    public int PessoaId { get; set; }

    // Coloque os demais campos aqui.

    public virtual Pessoa Pessoa { get; set; }
}

Pessoa would receive two more navigation properties:

public class Pessoa
{
    [Key]
    public int PessoaId { get; set; }

    [Required]
    public String NomeOuRazaoSocial { get; set; }

    // As duas propriedades de navegação vão aqui
    public virtual Cliente Cliente { get; set; }
    public virtual Fornecedor Fornecedor { get; set; }
}

That is, a Pessoa can be a Cliente , a Fornecedor , both or none.

Your modeling is ok but needs some tweaking, especially since you have omitted one of the best features of the Entity Framework, which is code-level specialization:

[Table("pessoa")]
// Não há motivo para usar partial classes em Models. 
// Você pode retirar a declaração.
public class pessoa
{
    // Construtores **nunca** devem ser usados para inicializar 
    // propriedades de navegação, então estou comentando.
    /* [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public pessoa()
    {
        cliente = new HashSet<cliente>();
        fornecedor = new HashSet<fornecedor>();
        pessoafisica = new HashSet<pessoafisica>();
        pessoajuridica = new HashSet<pessoajuridica>();
    } */

    [Key]
    public int idPessoa { get; set; }

    [Required]
    [StringLength(90)]
    public string nomeRazaoSocial { get; set; }

    // Essa propriedade não precisa.
    // public bool pf { get; set; }
}


[Table("pessoafisica")]
public class pessoafisica : pessoa
{
    // A chave já está em pessoa, então não precisa estar aqui.
    // [Key]
    // public int idPessoaFisica { get; set; }

    [StringLength(15)]
    public string cpf { get; set; }

    // Mesma coisa do comentário anterior.
    // public int idPessoa { get; set; }
    // public virtual pessoa pessoa { get; set; }
}


[Table("pessoajuridica")]
public class pessoajuridica : pessoa
{
    // Idem
    // [Key]
    // public int idPessoaJuridica { get; set; }

    [StringLength(45)]
    public string cnpj { get; set; }

    // Idem
    // public int idPessoa { get; set; }    
    // public virtual pessoa pessoa { get; set; }
}
  

If I want to assemble a listing of all people, with the columns person_id, nameOrSocial, CPF / CNPJ.

All people:

var pessoas = db.Pessoas.ToList(); // Sem CPF/CNPJ

All people with CPF and CNPJ:

var pessoas = db.PessoasFisicas
                .Select(pf => new { 
                              NomeOuRazaoSocial = pf.nomeRazaoSocial, 
                              CpfCnpj = pf.cpf
                       })
                .ToList()
                .Concat(db.PessoasJuridicas
                          .Select(pj => new { 
                             NomeOuRazaoSocial = pj.nomeRazaoSocial,
                             CpfCnpj = pj.cnpj
                          })
                          .ToList());

Using a ViewModel :

var pessoas = db.PessoasFisicas
                .Select(pf => new PessoaViewModel { 
                              NomeOuRazaoSocial = pf.nomeRazaoSocial, 
                              CpfCnpj = pf.cpf
                       })
                .ToList()
                .Concat(db.PessoasJuridicas
                          .Select(pj => new PessoaViewModel { 
                             NomeOuRazaoSocial = pj.nomeRazaoSocial,
                             CpfCnpj = pj.cnpj
                          })
                          .ToList());
  

In this case I would have to use if else to know if it is PF or PJ and to know if I search the information in the personal or personal object?

You do not need any of this. Just map 3 contexts and select from each of them:

public DbSet<Pessoa> Pessoas { get; set; }
public DbSet<PessoaFisica> PessoasFisicas { get; set; }
public DbSet<PessoaJuridica> PessoasJuridicas { get; set; }
  

Is there any strategy in Entity so that the person object knows where it should get this information from?

Checking the object:

var pessoa = db.Pessoas.First(p => p.Id == 1);
if (pessoa is PessoaFisica) { /* Faça alguma coisa */ }
if (pessoa is PessoaJuridica) { /* Faça outra coisa */ }
    
09.03.2016 / 20:38
3

I solved this by creating a People table People have a Type field [Physical, Legal]

A Customer, points to a Person An Employee, points to a person etc ...

    
09.03.2016 / 21:33