Inheritance X Composition - MySQL C # Entity

2

I was having a question of inheritance modeling in C # involving Person, Individual, and Legal entity, but Cigano Morrison Mendez helped a lot! Now I have another question in another type of relationship. As I said, a person may be physical or legal. A person can still be a customer and / or supplier. And the customer may have related services. Here's the modeling:

Thetemplatesinthecodewere:

[Table("pessoa")]
public class pessoa
{

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

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

    public virtual fornecedor fornecedor { get; set; }

    public virtual cliente cliente { get; set; }


}

[Table("pessoafisica")]
public class pessoafisica : pessoa
{

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

}

[Table("pessoajuridica")]
public class pessoajuridica : pessoa
{
    [StringLength(45)]
    public string cnpj { get; set; }

}

[Table("cliente")]
public class cliente
{
    [Key, ForeignKey("pessoa")]
    public int idPessoa { get; set; }

    public virtual pessoa pessoa { get; set; }

}

[Table("fornecedor")]
public class fornecedor
{

    [Key, ForeignKey("pessoa")]
    public int idPessoa { get; set; }

    public virtual pessoa pessoa { get; set; }
}

So far everything has worked well ... the interaction with the bank for registration, editing and consultation is fine. However, at the time of registering the services I have a flea behind my ear. Conceptually speaking. I related customer service and my class stayed:

[Table("servico")]
public class servico
{
    [Key]
    public int idServico { get; set; }

    [ForeignKey("cliente")]
    public int idCliente { get; set; }

    public string descricao { get; set; }

    public virtual cliente cliente { get; set; }
}

Clearly an Individual is a class inherited from Person, just as PersonJuridica is a class inherited from Person. Soon, if I had a table for people's addresses, in the address table I would use the Person table key to maintain the relationship. A person will always be OU personal or personal.

Now you have another question ... of the Supplier and Customer. A person MAY OR NOT be a supplier ... also MAY or NOT be a customer. And it can be either of them or not.

Although a customer or supplier is ALWAYS a person, the Service entity can only be associated with a Customer and never with a provider (at least in this application).

Here comes the first doubt ... for this desired concept, is this modeling correct? The keys in the tables, cardinality ... is that right?

Second doubt ...

I understand that in the Service table the idClient relationship key should contain the primary key of the Customer table, not the primary key of the Person table. IS THIS CONCEPT CORRECT?

Following the valuable help of Cigano, I set up these classes and in the controller of the service register the filling of the list of clients was as follows:

ViewBag.idCliente = new SelectList(db.cliente
                                            .Include(c => c.pessoa)
                                            .Select (c => new
                                            {
                                                idCliente = c.idPessoa,
                                                nomeRazaoSocial = c.pessoa.nomeRazaoSocial
                                            }).ToList(), "idCliente", "nomeRazaoSocial");

The application works, however when registering in the database, the idClient field of the service table receives the Person id field of the person table. And this is making me uncomfortable ...

The idClient field of the service table should not have the idClient field, which is the primary key of the Customer table? If so, how should I adjust my classes for this to work?

Thank you all for the help!

    
asked by anonymous 10.03.2016 / 23:42

2 answers

1

Thanks for the time, Cigano!

Modeling had a problem. Essentially, the client table should have as the primary key AND foreign key the user id:

BeforeithadidclienteasprimarykeyandidPessoaasforeignkey.Withthis,thebanksufferedaviolationbyputtingthepersonidintheservicetable.

Theclassesstayedasthegypsyspoke:

[Table("final.pessoa")]
public class pessoa
{
    [Key]
    public int idpessoa { get; set; }

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

    public virtual cliente cliente { get; set; }

}

[Table("final.pessoafisica")]
public class pessoafisica : pessoa
{

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

}

[Table("final.pessoajuridica")]
public class pessoajuridica : pessoa
{

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

}

[Table("final.cliente")]
public class cliente
{
    [Key, ForeignKey("pessoa")]
    public int idpessoa { get; set; }

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

    public virtual ICollection<servico> servico { get; set; }

    public virtual pessoa pessoa { get; set; }
}

[Table("final.servico")]
public class servico
{
    [Key]
    public int idservico { get; set; }

    public int idpessoa { get; set; }

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

    public virtual cliente cliente { get; set; }
}

In summary: in a cardinality relationship 0 ... 1, as in the case of client with person, use the primary key AND foreign key of the dependent table the id of the main entity.

    
13.03.2016 / 12:28
1

Your composition is incorrect. Cliente has relation 0 for 1 or 1 for 1 with Pessoa . As I said in the previous answer , the correct would you do:

[Table("cliente")]
public class cliente
{
    // Cliente não deve ter Id própria. Apenas idPessoa.
    // [Key]
    // public int idCliente {get; set;}

    [Key, ForeignKey("pessoa")]
    public int idPessoa { get; set; }

    public int idCliente_Grupo { get; set; }

    public virtual cliente_grupo cliente_grupo { get; set; }

    public virtual pessoa pessoa { get; set; }

    public virtual ICollection<servico> servico { get; set; }
}

The same goes for Fornecedor .

Just as an addendum, I would not use Linq to mount the query because Linq's lazy / anticipated load support is limited. I would do so:

ViewBag.idCliente = new SelectList(db.Clientes
                                     .Include(c => c.Pessoa)
                                     .Select(c => new
                                      {
                                          idCliente = c.idPessoa,
                                          nomeRazaoSocial = c.Pessoa.nomeRazaoSocial
                                      }).ToList(), "idCliente", "nomeRazaoSocial");
  

Is this modeling correct? The keys in the tables, cardinality ... is that right?

With your changes, yes. Perfect, I would say.

  

I understand that in the Servico table the idCliente relationship key must contain the primary key of the Cliente table, not the primary key of the Pessoa table. IS THAT CONCEPT IS CORRECT?

Yes, but since the key of Cliente is the key of Pessoa (because Cliente is, by composition, a specialization of Pessoa ), it does the same.

If you want to keep the idCliente name in the modeling, no problem. It's even better because you explain by naming how Servico is related to Cliente .

  

The idCliente field in the Servico table should not have the idCliente field, which is the primary key of the Cliente ??

No. idCliente is conceptually equivalent to idPessoa , precisely because Cliente is the specialization of Pessoa , by composition. Therefore, it is correct to set SelectList to idPessoa because data selection starts from Cliente , not Pessoa , already checking, therefore, whether Pessoa is Cliente or not% / p>     

11.03.2016 / 05:36