none
Mapeamento Many to Many com campo extra no EF6 RRS feed

  • Pergunta

  • Fala Galera boa noite,

    Gostaria de pedir ajuda de vocês...Estou trabalhando com EF6 em C#...

    Tenho 2 Tabelas:
    Usuario
    Cursos

    Estou utilizando o EF6 com relacionamento MxM, realizando o MAP na Classe Usuarios para a tabela "Usuario_Cursos" conforme o codigo abaixo:

    this.HasMany<Curso>(c => c.Cursos)
    .WithMany(t => t.Usuarios)
    .Map(uc =>
    {
    uc.ToTable("Usuario_Cursos"); 
    uc.MapLeftKey("UsuarioID"); 
    uc.MapRightKey("CursoID");
    });

    Esta tudo funcionando perfeitamente bem consigo incluir, excluir, alterar sem problemas, Porem apareceu a necessidade de saber quando o "ALUNO" foi cadastrado no CURSO, então pensei em adicionar na Tabela de Relacionamento uma coluna do tipo DATETIME para que eu possa saber exatamente quando o aluno foi incluído no curso..

    Gostaria da ajuda do pessoal para saber como devo proceder no EF6 para realizar esse mapeamento e conseguir capturar esse campo DateTime junto com a tabela Cursos..

    Obrigado!

    terça-feira, 3 de julho de 2018 00:03

Respostas

  • Diego,

    Criei um PULL REQUEST com todas as modificações.

    Primeiro foi criado a classe UsuarioCurso, ela contem as informações adicionais, através da herança de DataLog:

    public class UsuarioCurso : DataLog
    {
         public int UsuarioID { get; set; }
         public int CursoID { get; set; }
         public Curso Curso { get; set; }
         public Usuario Usuario { get; set; }
    }

    Para ela ser adicionada ao banco criei o mapeamento:

    public class UsuarioCursoMap : EntityTypeConfiguration<UsuarioCurso>
    {
        public UsuarioCursoMap()
        {
            this.HasKey(k => new { k.UsuarioID, k.CursoID});
            this.HasRequired(r => r.Curso).WithMany(d => d.UsuarioCurso).HasForeignKey(fk => fk.CursoID);
            this.HasRequired(r => r.Usuario).WithMany(d => d.UsuarioCurso).HasForeignKey(fk => fk.UsuarioID);
        }
    }

    Além disso as queries que tinham include direto da classe, teve que ser modificada:

    Antes:

     var data = _context.Usuarios.Include(e => e.s.Curso)

    Para:

    var data = _context.Usuarios.Include(e => e.UsuarioCurso.Select(s => s.Curso))

    Bom, se tiver outro problema ou duvida, só chamar.


    Espero ter ajudado! Se consegui, não esquece de marcar no fórum como útil! Obrigado :)
    #fullstack dev - MCSA, MCTS and actually blogging at www.saindodacaixinha.com.br

    • Marcado como Resposta Diego Cataldi quinta-feira, 5 de julho de 2018 05:48
    quarta-feira, 4 de julho de 2018 13:29
  • Sim, está certo!

    Você do && a.UsuarioID == usuarioid pois já esta sendo utilizado esse critério no Where.

    PS: Dá uma pesquisada sobre Dapper, ela vai ser mais performatica que o EF para casoso como esse!

    abs


    Espero ter ajudado! Se consegui, não esquece de marcar no fórum como útil! Obrigado :)
    #fullstack dev - MCSA, MCTS and actually blogging at www.saindodacaixinha.com.br

    • Marcado como Resposta Diego Cataldi quinta-feira, 5 de julho de 2018 08:31
    quinta-feira, 5 de julho de 2018 07:13

Todas as Respostas

  • Diego,

    Uma maneira de conseguir adicionar um terceiro campo seria criar uma class Usuario_Cursos e entao fazer o mapeamento dela. Dessa forma ela ficará disponível para o EntityFramework, consequentemente sendo possível fazer a manipulação de seus dados.


    Espero ter ajudado! Se consegui, não esquece de marcar no fórum como útil! Obrigado :)
    #fullstack dev - MCSA, MCTS and actually blogging at www.saindodacaixinha.com.br

    terça-feira, 3 de julho de 2018 01:01
  • Você diz manter o mapeamento MxM como está e criar uma nova classe com um novo map e buscar seus dados quando eu precisar?
    terça-feira, 3 de julho de 2018 04:19
  • Exatamente. Acredito que seja a melhor estratégia, uma vez que você cria esse mapeamento, não tem controle nenhum sobre ele a partir do Entity, qualquer workaround consiste em tentar controlar essa data via Sql seja com default value, trigger, update etc.

    Espero ter ajudado! Se consegui, não esquece de marcar no fórum como útil! Obrigado :)
    #fullstack dev - MCSA, MCTS and actually blogging at www.saindodacaixinha.com.br

    terça-feira, 3 de julho de 2018 12:40
  • Entendi Bruno, mas acho q nao vou conseguir implementar...

    Se eu colocar meu projeto no GITHUB você consegue me dar 1 ajuda na implementação desta classe apenas?, digo na criação do Mapeamento necessario e um crud basico?

    obrigado!

    terça-feira, 3 de julho de 2018 12:42
  • Sim, consigo! Põe no Git e tocamos essa questão!

    Espero ter ajudado! Se consegui, não esquece de marcar no fórum como útil! Obrigado :)
    #fullstack dev - MCSA, MCTS and actually blogging at www.saindodacaixinha.com.br

    terça-feira, 3 de julho de 2018 15:48
  • Coloquei meu projeto backend no GITHUB para você dar 1 olhada!

    https://github.com/dicataldisky/DACSistemas.Central-de-Cursos.BackEnd

    se quiser posso te mandar inbox os dados do DB para você se conectar e ver como ficou a estrutura, ele esta em desenvolvimento se der problema lá nao da nada! rs

    terça-feira, 3 de julho de 2018 23:09
  • Diego,

    Criei um PULL REQUEST com todas as modificações.

    Primeiro foi criado a classe UsuarioCurso, ela contem as informações adicionais, através da herança de DataLog:

    public class UsuarioCurso : DataLog
    {
         public int UsuarioID { get; set; }
         public int CursoID { get; set; }
         public Curso Curso { get; set; }
         public Usuario Usuario { get; set; }
    }

    Para ela ser adicionada ao banco criei o mapeamento:

    public class UsuarioCursoMap : EntityTypeConfiguration<UsuarioCurso>
    {
        public UsuarioCursoMap()
        {
            this.HasKey(k => new { k.UsuarioID, k.CursoID});
            this.HasRequired(r => r.Curso).WithMany(d => d.UsuarioCurso).HasForeignKey(fk => fk.CursoID);
            this.HasRequired(r => r.Usuario).WithMany(d => d.UsuarioCurso).HasForeignKey(fk => fk.UsuarioID);
        }
    }

    Além disso as queries que tinham include direto da classe, teve que ser modificada:

    Antes:

     var data = _context.Usuarios.Include(e => e.s.Curso)

    Para:

    var data = _context.Usuarios.Include(e => e.UsuarioCurso.Select(s => s.Curso))

    Bom, se tiver outro problema ou duvida, só chamar.


    Espero ter ajudado! Se consegui, não esquece de marcar no fórum como útil! Obrigado :)
    #fullstack dev - MCSA, MCTS and actually blogging at www.saindodacaixinha.com.br

    • Marcado como Resposta Diego Cataldi quinta-feira, 5 de julho de 2018 05:48
    quarta-feira, 4 de julho de 2018 13:29
  • Fala Bruno Boa Tarde! Antes de tudo gostaria de agradecer a ajuda que você está me dando!

    O relacionamento deu certo!
    Agora quando rodo a consulta abaixo está retornando certo o curso conforme a referencia da tabela Usuario_Cursos :)


    P
    Eu criei na tabela do mysql Usuario_Cursos a coluna DataInclusao do tipo Datetime e para tentar listar na minha consulta dentro do array do grupo.

    1 - Adicionei no código na classe ListCursoViewModel a propriedade DataInclusao do tipo DateTime conforme abaixo:

    public class ListCursoViewModel
        {
            public int? CursoID { get; set; }
            public string Nome { get; set; }
            public string Descricao { get; set; }
            public Int16 CargaHoraria  { get; set; }
            public bool FinalDeSemana { get; set; }
            public DateTime DataInclusao { get; set; }
    
        }

    na classe UsuarioCurso fiz a mesma coisa:

        public class UsuarioCurso
        {
            public int UsuarioID { get; set; }
            public int CursoID { get; set; }
            public DateTime DataInclusao { get; set; }
            public Curso Curso { get; set; }
            public Usuario Usuario { get; set; }
        }

    Adicionei na linha em vermelho com 1 filtro... está funcionou, mas gostaria da sua opnião se está correto rsrs

     public IList<ListUsuarioViewModel> Get(int usuarioid)
            {
                var data = _context.Usuarios
                    .Include(e => e.Enderecos)
                    .Include(e => e.UsuarioCurso.Select(s => s.Curso))
                    .Select(x => new ListUsuarioViewModel
                    {
                        UsuarioID = x.UsuarioID,
                        NomeCompleto = x.Nome,
                        Email = x.Email,
                        Foto = x.Foto,
                        Sexo = x.Sexo,
                        EstadoCivil = x.EstadoCivil,
                        DataDeNascimento = x.DataNascimento,
                        Telefone = x.Telefone,
                        TelefonDeEmergencia = x.TelefoneEmergencia,
                        Celular = x.Celular,
                        Enderecos = x.Enderecos.Select(e => new ListEnderecoViewModel
                        {
                            EnderecoID = e.EnderecoID,
                            CEP = e.CEP,
                            Logradouro = e.Logradouro,
                            Numero = e.Numero,
                            Complemento = e.Complemento,
                            Bairro = e.Bairro,
                            Cidade = e.Localidade,
                            UF = e.UF
                        }).ToList(),
                        Grupos = x.Grupos.Select(g => new ListGrupoViewModel {
                            GrupoID = g.GrupoID,
                            Descricao = g.Descricao,
                            Instrutor = g.Instrutor
                        }).ToList(),
                        Cursos = x.UsuarioCurso.Select(a => a.Curso).Select(c => new ListCursoViewModel
                        { 
                            DataInclusao = x.UsuarioCurso.FirstOrDefault(a => a.CursoID == c.CursoID && a.UsuarioID == usuarioid).DataInclusao,
                            CursoID = c.CursoID,
                            Nome = c.Nome,
                            Descricao = c.Descricao,
                            CargaHoraria = c.CargaHoraria,
                            FinalDeSemana = c.FinalDeSemana
                        }).ToList(),
                        Habilitacoes = x.Habilitacoes.Select(h => new ListHabilitacaoViewModel
                        {
                            HabilitacaoID = h.HabilitacaoID,
                            Associacao = h.Associacao,
                            Nivel = h.Nivel,
                            DataDeFiliacao = h.DataDeFiliacao
                        }).ToList()
                    })
                    .Where(u => u.UsuarioID == usuarioid)
                    .AsNoTracking()
                    .ToList();
                
                return data;
            }

    Mas uma vez obrigado pela ajuda!
    Abraços!


    • Marcado como Resposta Diego Cataldi quinta-feira, 5 de julho de 2018 05:48
    • Não Marcado como Resposta Diego Cataldi quinta-feira, 5 de julho de 2018 05:48
    • Editado Diego Cataldi quinta-feira, 5 de julho de 2018 05:52
    quinta-feira, 5 de julho de 2018 05:47
  • Sim, está certo!

    Você do && a.UsuarioID == usuarioid pois já esta sendo utilizado esse critério no Where.

    PS: Dá uma pesquisada sobre Dapper, ela vai ser mais performatica que o EF para casoso como esse!

    abs


    Espero ter ajudado! Se consegui, não esquece de marcar no fórum como útil! Obrigado :)
    #fullstack dev - MCSA, MCTS and actually blogging at www.saindodacaixinha.com.br

    • Marcado como Resposta Diego Cataldi quinta-feira, 5 de julho de 2018 08:31
    quinta-feira, 5 de julho de 2018 07:13