C# and Entity Framework with Foreignkey between classes

Asked

Viewed 302 times

3

People in my projects .Net MVC use the structure below. My projects, are with Entity Framework.

The briefcase Entidades, are the classes I use in DbContext.

Minha estrutura de projeto

Detailing the problem

I have the class Cliente, that has ForeignKey for the class Pessoa. Not to have to DbContext.Cliente.Include("Pessoa"), created the PessoaDTO which is a class with some class fields Pessoa and how PessoaDTO has a Interface I can use it in other classes like Filial and the like.

And this way, I can ride a ViewPartial, to display the person’s data in a "generic" and several Views.

Doubts

  • There is something more intelligent and performative for the above structure?
  • Use DTOs they may have methods?

Example of use

public ActionResult Detalhar(int id)
{
    using (var db = new Conexao())
    {
        var registro = db.Cliente.Find(id);
        registro.DTO();

        return View(registro);
    }
}

Sources of classes

Classe Pessoa

public class Pessoa : IEntidadeBase, IFixo
{
    [Key]
    public int PessoaID { get; set; }

    [Obrigatorio]
    [Display(Name = "Tipo de Pessoa")]
    public int TipoPessoaID { get; set; }

    [Obrigatorio]
    [Display(Name = "Sexo")]
    public int SexoID { get; set; }

    [Display(Name = "CPF/CNPJ")]
    public string CNPJCPF { get; set; }

    [Display(Name = "Identificação Interna / Matrícula")]
    public string IdentificacaoInterna { get; set; }

    [Obrigatorio]
    [Display(Name = "Nome/Nome Fantasia")]
    public string Nome { get; set; }

Client class

public class Cliente : IEntidadeBase, IFixo, IPessoaDTO
{
    [Key]
    public int ClienteID { get; set; }

    public int PessoaID { get; set; }

    [ForeignKey("PessoaID")]
    public virtual Pessoa Pessoa { get; set; }
    [NotMapped]
    public PessoaDTO PessoaDTO { get; set; }

    public void DTO()
    {
        if (Pessoa != null)
        {                
            PessoaDTO = new PessoaDTO();
            PessoaDTO.Popular(Pessoa);
        }
    }
}

Classe Pessoadto

public class PessoaDTO 
{
    public string Nome { get; set; }
    [Display(Name = "CNPJ/CPF")]
    public string CNPJCPF { get; set; }
    [Display(Name = "Tipo de Pessoa")]
    public string TipoDePessoa { get; set; }
    public string Sexo { get; set; }

    public string Rotulo { get; set; }

    public void Popular(Pessoa registro)
    {
        Nome = registro.Nome;
        CNPJCPF = registro.CNPJCPF;

        TipoDePessoa = registro.TipoPessoaID == 1 ? "Física" : registro.TipoPessoaID == 2 ? "Juridica" : String.Empty;
        Sexo = registro.SexoID == 1 ? "Masculino" : registro.SexoID == 2 ? "Feminino" : "Não aplicável";            

        Rotulo = String.Format("{0} [{1}]", Nome, CNPJCPF);
    }
}
  • I don’t know if it’s the intention, but you want to use the DDD or "Domain", it’s just the same name, because if you’re considering the DDD, you couldn’t associate your entities with Dtos, maintain infrastructure dependency, have [KEY] annotations etc in the entities, or even access the dbcontext directly from the controller since you have the repositories, but if it really makes a difference to you, you could create DTOS, MODELS VIEW or DYNAMICS and use the micro ORM to make the custom querys for the output you want. Patterns in this case would be partially CQRS.

1 answer

0

Use the following Techniques: Extension Methods "Extensions Methods" and Reflection "Reflection"

Extension Methods: will give you the freedom to reference a project to be shared and Reflection: you can copy the information of the properties of objects containing common names and types.

var registro = db.Cliente.Find(id);
         
var dto = registro.ConverterObjeto<Pessoa, PessoaDTO>();
        
return View(dto);

public static class TiposComplexos
{
    public static Destino ConverterObjeto<Origem, Destino>(this Origem origem)
    {
        var destino = Activator.CreateInstance<Destino>();

        foreach (var propriedadeOrigem in origem.GetType().GetProperties())
        {
            var propriedadeDestino = destino.GetType().GetProperty(propriedadeOrigem.Name);

            if (propriedadeDestino != null && propriedadeOrigem.Name == propriedadeDestino.Name)
                propriedadeDestino.SetValue(destino, propriedadeOrigem.GetValue(origem, null));
        }

        return destino;
    }
}
  • The Automapper does this and I believe that more performatively, because it is in the application Startup, no?

  • Automapper is certainly an already tested, stable and community-approved framework, but the example I quoted was in the case of an application that does not support Automaper versions, such as a legacy system, so we have to take the scenario, After an analysis of the Automapper code on github, it is implemented using the "Reflection" feature mentioned in the example. Or also depending on the client he does not approve the use of framework in his architecture "unfortunately in the real world happens this", hence there are cases that should reinvent the wheel.

Browser other questions tagged

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