Table Relationship FluentAPI

1

I'm trying to make a table relationship, using FluentAPI with Entity Framework, in which my purpose are 3 entities:

public class Empresa
{
    public Empresa() 
    {
        this.Gerentes = new HashSet<Gerente>();
    }

    public int EmpresaId { get; set; }
    public string EmpresaNome { get; set; }

    public virtual ICollection<Gerente> Gerentes { get; set; }
}

public class Gerente
{
    public Gerente()
    {
        this.Empresas = new HashSet<Empresa>();
    }

    public int GerenteId { get; set; }
    public string GerenteNome { get; set; }

    public virtual ICollection<Empresa> Empresas { get; set; }
}

public class Projeto
{
    public int ProjetoId { get; set; }
    public string ProjetoNome { get; set; }
}

Problem:

A manager can be a manager in more than one company, but a project only belongs to a manager in the specific company.

About the Company x Manager relationship, I came up with this result:

modelBuilder.Entity<Empresa>()
    .HasMany<Gerente>(s => s.Gerentes)
    .WithMany(c => c.Empresas)
    .Map(cs =>
            {
                cs.MapLeftKey("EmpresaId");
                cs.MapRightKey("GerenteId");
                cs.ToTable("EmpresaGerente");
            });

Now my problem is how to relate the project to the manager in that company.

    
asked by anonymous 06.06.2017 / 17:03

1 answer

1

If the project belongs to a manager in a specific company, I would do this:

public class Projeto
{
    public int ProjetoId { get; set; }
    public string ProjetoNome { get; set; }
    public int EmpresaId { get; set; }
    public int GerenteId { get; set; }
    public virtual Empresa Empresa { get; set; }
    public virtual Gerente Gerente { get; set; }
}

modelBuilder.Entity<Projeto>()
    .HasRequired(p => p.Gerente)
    .WithMany()
    .HasForeignKey(p => p.GerenteId);

modelBuilder.Entity<Projeto>()
    .HasRequired(p => p.Empresa)
    .WithMany()
    .HasForeignKey(p => p.EmpresaId);

I've omitted the navigation property in WithMany() methods for simplicity, but you'd probably create a public virtual ICollection<Projeto> in the Gerente class and the Empresa class and would include the expression lambda according to the two WithMany() , although this is optional.

However, this in and of itself does not prevent you from assigning a company that is not linked to the manager of that project. This control should stay in your application (or your class, depending on how you work). A simple example just to give you an idea:

public class CadastraProjetoRequest
{
    public string ProjetoNome { get; set; }
    public int EmpresaId { get; set; }
    public int GerenteId { get; set; }
}

public void CadastraProjeto(CadastraProjetoRequest request)
{
    using(var ctx = new MeuDbContext())
    {
        bool gerenteDaEmpresa = ctx.Empresas.Any(e => e.EmpresaId == request.EmpresaId && e.Gerentes.Any(g => g.GerenteId == request.GerenteId));

        if (!gerenteDaEmpresa)
            throw new InvalidOperationException("Essa empresa não possui esse gerente!");

        // criar e salvar o projeto...

    }
}

Of course if you change the manager or the company of a project, this rule would have to be validated there too. If you prefer, you can create a method in the class to assign the manager and company and validate there yourself (hence it would be encapsulated in the class, and it would make no difference if it was creation or change). The downside of this is that you would have to read the company object of your DbContext by doing Include(e => e.Gerentes) (or enabling lazy load ), which would > cost of reading more bank data (since the previous form using Any() direct in DbContext performs better), but it's up to you to decide.

    
07.06.2017 / 05:09