Correct Inheritance in Entity Framework

Asked

Viewed 606 times

3

I have a mother class DadosClientes and two child classes DadosClientesPF, and DadosClientesPJ.

Instance DadosCliente has the field: Nome, Telefone

Instance DadosClientePF has the field: CPF

Instance DadosClientePJ has the field: CNPJ

The client object has an instance DadosClientes, but it only accesses the fields of DadosCliente, how do I access the fields CPF and CNPJ?

  • 1

    Could you provide the code so we can help you more precisely? I suppose you’re using inheritance to compose right Customer, Data, Data?

  • 1

    Creating an instance of DadosClientesPF or DadosClientesPJ. You cannot access what does not exist. If the problem is not just that, explain it better and put some example.

  • 1

    @Kleberbarros, as the bigown pointed out, I don’t think it’s a good idea to box and Unbox DadosClientePF and DadosClientePJ. In any case, I advise you to read more about inheritance models in EF: Table-per-Type (TPT), Table-per-Hierarchy (TPH) and Table-per-Concrete (TPC). http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines

  • 1

    @Tobymosque Box and Unbox is a terminology used for value-types. You were probably referring to type-Casts between base and derivative classes.

  • Fault mine, thanks for the correction.

  • Take a look at [tour]. You can accept an answer if it solved your problem. You can vote on every post on the site as well. Did any help you more? You need something to be improved?

Show 1 more comment

3 answers

4

If you want to take a property, you have to instantiate a class that has this property. So if you want the CPF, needs to instantiate the DadosCLientesPF. Instantiate DadosClientes there is no way to get the number simply because it does not exist in this class.

If you are using a method you receive DadosClientes and needs to access something that is not available on it, is doing something wrong as well. In this case the correct would be to have separate methods to deal with DadosClientesPF, with DadosCLientesPJ and maybe even keep what deals only with the DadosClientes if it’s useful, which I doubt.

Especially in the taste of the solution given in the other answer. I am not a purist but that is not object-oriented programming. Methods should not have to know how to handle derivative objects of the expected type. When this is necessary, specialized methods should be created, otherwise if it is later created ClientesDadosEstrangeiro would have to tinker with the implementation of this method. Depending on the scenario it may not be problematic but in others it may be. I don’t know if you need to use inheritance in this case, but if you’re gonna use it, do it for the right reasons, and use it the right way.

If you have separated into two classes, treat them as different things. If the intention is to treat them as if they were the same thing, do not separate.

But if your problem is polymorphism (not that it is the case), that is, you are instantiating the derived class but when you pass it to some method that expects the base class, then your problem is that the property needs to be virtual. This guarantees the polymorphism and will call the property correctly, since it will interpret the object with its type originally instantiated and not by the type concretely declared in the method parameter. Of course this only applies if the property exists in the base class.

Maybe you need reevaluate all your modeling.

4

After loading the object cliente comic book you can check the property type.

Example using the operator as:

using (var context = new Context())
{
    var cli = context.Clientes.Where(c => c.Id == idCli).Single();
    var pf = cli.DadosClientes as DadosClientePF;
    if (pf != null)
    {
        // pessoa física
        var cpf = pf.CPF;
    }

    var pj = cli.DadosClientes as DadosClientePJ;
    if (pj != null)
    {
        // pessoa jurídica
        var cnpj = pj.CNPJ;
    }
}

To create a new client, simply create one of the classes DadosClientePF or DadosClientePJ and assign to the property cli.DadosClientes:

using (var context = new Context())
{
    var cli = new Cliente();
    if (cnpj != null)
    {
        cli.DadosClientes = new DadosClientePJ
            {
                CNPJ = cnpj
            };
    }

    if (cpf != null)
    {
        cli.DadosClientes = new DadosClientePF
            {
                CPF = cpf
            };
    }

    if (cli.DadosClientes != null)
        cli.DadosClientes.Nome = nome;

    context.Clientes.Add(cli);
    context .SaveChanges();
}

1

Supposing that you have:

class DadosCliente
{
  public string Nome { get; set; }
  public string Telefone { get; set; }
}

class DadosClientePF : DadosCliente
{
  public string CPF { get; set; }
}

class DadosClientePJ : DadosCliente
{
  public string CNPJ { get; set; }
}

And instance a PF object:

DadosClientePF obj = new DadosClientePF{
  Nome = 'Nome',
  CPF = '000.000.000-00'
};

And then executes a method that takes a parameter of type Data:

void Testar(DadosCliente dados)

To access the properties of child classes in this method you need to check the type of instance and cast:

if (dados is DadosClientePJ)
{
    DadosClientePJ dadosPj = (DadosClientePJ)dados;
    Console.Write(dadosPj.CNPJ);
}
else if (dados is DadosClientePF)
{
    DadosClientePF dadosPf = (DadosClientePF)dados;
    Console.Write(dadosPf.CPF);
}

Browser other questions tagged

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