none
Modelando classe PESSOA e CLIENTES com herança

    Question

  • Olá,

    estou fazendo a implementação no projeto de estudo, uma classe PESSOA, que irá ter os dados básicos para as classes de FILIAIS, CLIENTES, FORNECEDORES e FUNCIONARIOS. 

    Então implementei a minha classe PESSOA da seguinte forma, ela herda os campos fixos de uma interface (IEntidadeBase)

    public class Pessoa : IEntidadeBase
        {
            [Key]
            public int PessoaID { get; set; }
            public int TipoPessoaID { get; set; }
            public int SexoID { get; set; }
            public string CNPJCPF { get; set; }
    
            /* Campos fixos */
            public int EmpresaID { get; set; }
            public string Fixo { get; set; }
            public string Status { get; set; }
            public string Apagado { get; set; }
            public DateTime? DtApagado { get; set; }
            public int UsuCad { get; set; }
            public DateTime DtCad { get; set; }
            public int UsuAlt { get; set; }
            public DateTime DtAlt { get; set; }
            public int UsuUltAlt { get; set; }
            public DateTime DtUltAlt { get; set; }
    
            [ForeignKey("UsuCad")]
            public virtual Usuario UsuarioCad { get; set; }
            [ForeignKey("UsuAlt")]
            public virtual Usuario UsuarioAlt { get; set; }
            [ForeignKey("UsuUltAlt")]
            public virtual Usuario UsuarioUltAlt { get; set; }
            [ForeignKey("EmpresaID")]
            public virtual Empresa Empresa { get; set; }
        }

    A classe CLIENTE fiz a implementação da seguinte forma:

        public class Cliente : Pessoa
        {
            [Key]
            public int ClienteID { get; set; }
            public decimal LimiteCredito { get; set; }
        }

    Olhei este exemplo do Fernando (http://ferhenriquef.com/2012/06/11/mapeando-heranas-no-entity-framework-code-first/) e tem o exemplo acima. Porém teoricamente se eu quiser colocar no Cliente os campos fixos da IEntidadeBase, teria como fazer?

    Além disto, se eu quiser fazer uma lista de TELEFONES, aonde e como devo coloca-la. A classe eu mostro abaixo, mas como coloca-la dentro da classe Cliente? Ou na classe TELEFONE coloco ClienteID?

        public class Telefone : IEntidadeBase
        {
            [Key]
            public int TelefoneID { get; set; }
            public string Telefone { get; set; }
            public string Tipo { get; set; }
    
            /* Campos fixos */
            public int EmpresaID { get; set; }
            public string Fixo { get; set; }
            public string Status { get; set; }
            public string Apagado { get; set; }
            public DateTime? DtApagado { get; set; }
            public int UsuCad { get; set; }
            public DateTime DtCad { get; set; }
            public int UsuAlt { get; set; }
            public DateTime DtAlt { get; set; }
            public int UsuUltAlt { get; set; }
            public DateTime DtUltAlt { get; set; }
    
            [ForeignKey("UsuCad")]
            public virtual Usuario UsuarioCad { get; set; }
            [ForeignKey("UsuAlt")]
            public virtual Usuario UsuarioAlt { get; set; }
            [ForeignKey("UsuUltAlt")]
            public virtual Usuario UsuarioUltAlt { get; set; }
            [ForeignKey("EmpresaID")]
            public virtual Empresa Empresa { get; set; }
        }

    Mas será que não seria mais fácil fazer a classe PESSOA e dentro da classe CLIENTE, fazer um atributo ser do tipo PESSOA?
    Assim eu iria manter a FK que existe, e com os campos fixo da IEntidadeBase...

    Ou estou viajando?

    Abs...


    Marlon Tiedt
    www.sesmt.com.br



    Wednesday, July 25, 2012 2:23 PM

Answers

All replies

  • Olá Marlon,

    Obrigado por ter buscado o exemplo no meu blog :)

    Quando vc diz: "Porém teoricamente se eu quiser colocar no Cliente os campos fixos da IEntidadeBase, teria como fazer?" Na verdade os campos já estão lá, pois vc esta fazendo uma herança de Pessoa. Vc gostaria de sobrescrever alguma das propriedades?

    Vc também comenta: "e eu quiser fazer uma lista de TELEFONES, aonde e como devo coloca-la" No caso, se os telefones fizerem parte apenas da classe Cliente, então vc deve fazer assim:

        public class Cliente : Pessoa
        {
            [Key]
            public int ClienteID { get; set; }
            public decimal LimiteCredito { get; set; }
            public List<Telefone> Telefones { get; set; }
            
            public Cliente()
            {
                this.Telefones = new List<Telefone>();
            }
        }



    E na classe Telefone deve incluir uma propriedade do tipo Cliente.

    []s!

    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    Thursday, July 26, 2012 12:05 PM
  • Olá Fernando,

    "Vc gostaria de sobrescrever alguma das propriedades?" - Quero fazer isto mesmo. Pois todas as minhas tabelas tem os campo da IEntidadeBase, para controle. E conforme vi no seu exemplo, a forma que montei somente irá ter os campos na tabela "PESSOA" e eu preciso que seja na tabela "PESSOA" e "CLIENTE".

    Por acaso no seu blog, você teria algum exemplo de cadastro parecido com a ideia da classe "TELEFONE".

    Abs


    Marlon Tiedt
    www.sesmt.com.br

    Thursday, July 26, 2012 12:28 PM
  • Olá Marlon,

    Neste caso, eu acredito que o EF Code First sempre irá adicionar os campos da classe Pessoa na tabela Pessoa. Uma solução para isso, é fazer com que a classe Pessoa não implemente a interfaceIEntidadeBase (já que realmente ele não é uma entidade da base) e fazer com que a classe Cliente implemente essa interface. Isso irá resolver este problema.

    Um post que fala sobre isso é este aqui: http://ferhenriquef.com/2012/07/07/ef-code-first-design-patterns-asp-net-multi-camadas-e-muito-trabalho/

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    • Marked as answer by Marlon Tiedt Thursday, July 26, 2012 3:16 PM
    Thursday, July 26, 2012 12:34 PM
  • Olá Fernando, 

    então pensando neste caso, então tenho que fazer diferente a minha classe.
    PESSOA e CLIENTE herdam de IEntidadeBase, e dentro de cliente eu ter um atributo PessoaID com FK para PESSOA.

    Deste forma será que estaria correto o meu pensamento?

    Abs


    Marlon Tiedt
    www.sesmt.com.br

    Thursday, July 26, 2012 12:59 PM
  • Olá Marlon,

    Vc tem de avaliar se a sua classe Pessoa realmente deve existir. Talvez a entidade IEntidadeBase já de conta do recado e vc não precise necessariamente utilizar a classe Pessoa.

    Quais as demais classes do seu modelo que tem essa herança?

    O uso de heranças serve para compartilhar um comportamento ou uma estrutura. Reparei que sua classe Pessoa não possui nenhum método, então não compartilha comportamentos. E a entidade IEntidadeBase compartilha uma estrutura. Então a classe Pessoa acaba tornando-se redundante no modelo.

    Essa classe Pessoa tem algum uso mais concreto?

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    Thursday, July 26, 2012 1:05 PM
  • Olá Fernando.

    A classe PESSOA seria o base para criar as classes CLIENTE, FORNECEDOR, TRANSPORTADORA, FABRICANTE e afins. Ou seja a classe PESSOA, teria os atributos comuns das outras classes. Exemplo: Tipo de pessoa (Fisica/Juridica), Sexo (Masculino/Feminio/ND), CPF/CNPJ, a lista de TELEFONES, lista de ENDEREÇOS.

    A nas classes CLIENTES e afins, teria os campos especificios. Exemplo: Limite de crédito, status do cliente, total de compras.

    Consegui te explicar um pouco melhor a minha ideia?

    Abs

    Marlon Tiedt
    www.sesmt.com.br

    Thursday, July 26, 2012 2:05 PM
  • Marlon,

    Achei um artigo falando sobre o que vc precisa. Chama-se Table per Concrete Type.

    Bem interessante: http://weblogs.asp.net/manavi/archive/2011/01/03/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines.aspx

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    • Marked as answer by Marlon Tiedt Thursday, July 26, 2012 3:16 PM
    Thursday, July 26, 2012 2:50 PM
  • Olá Fernando,

    valeu pela ajuda. Como estamos aqui para aprender vou deixar a minha contribuição sobre o assunto. O link que você me passou, é bem interessante a implementação. Com ela em vez de usar uma interface, posso usar uma classe abstrata, e terei todos os atributos fixos, que estarão em todas as tabelas, dentro desta classe abstrata.

    var query = from b in context.PESSOA select b;

    Além disto, se fizer a pesquisa acima, ele faz um UNION ALL e teoricamente posso trazer tudo de todas as classes, que herdam desta classe abstrata. (Pelo menos eu entendi isto :) )

    O ganho de manutenção com isto será gigante. Pois não tenho que sobre escrever os atributos, como acontece com a interface.

    O Mortenza escreveu 3 artigos sobre o assunto, que coloco para quem quiser ver: Link 1Link 2 e Link 3.


    Abs


    Marlon Tiedt
    www.sesmt.com.br

    Thursday, July 26, 2012 3:15 PM
  • Olá,

    Estou começando com dbContext e estou com um problema.... Estou criando classes herdadas PESSOA e CLIENTE... Eu usei model first criando as classes com DbContext generator, mas quando tento executar uma query em CLIENTE eu não estou conseguindo....

    Dim Ps = FROM P in context.PESSOA.ofType(Of CLIENTE).toList

    Recebo um erro de que CLIENTE não é queryable?!?!?

    Se selecionar todas as PESSOAS ( FROM P in PESSOA.toList) tudo bem.... 

    Como faço para dar um select só em quem é cliente e não em todas as pessoas?

    Abs.

    Sunday, August 12, 2012 8:57 PM
  • Olá Luzio,

    Veja se isto lhe ajuda:

    Dim query = (From p In context.PESSOA Where (TypeOf p Is Cliente)).ToList

    []s!

    Fernando Henrique Inocêncio Borba Ferreira
    Microsoft MVP - Data Platform Development
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique
    Entity Framework - Brasil: https://www.facebook.com/EntityFrameworkBrasil

    Monday, August 13, 2012 2:52 AM
  • Fernando,

    Era isso que estava procurando mas só encontrava exemplos com .typeof(of ).

    Muito Obrigado.

    Monday, August 13, 2012 12:30 PM