none
Entity Framework - Inserção e Atualização com Many to Many RRS feed

  • Pergunta

  • Pessoal boa noite tudo certo ?

    Seguinte estou com duvidas de como devo persistir meus dados com o entity framework no banco de dados, eu tenho uma entidade Produtos que tem uma lista de promoções, é um N pra N biirecional, eu gostaria de cadastrar um produto já vinculando a ele promoções existentes na base de dados, porém fazendo desse jeito :

                        Produto produto = new Produto
                        { 
                            nome = txtDescricao.Text,
                            preco = Convert.ToDecimal(txtPreco.Text),
                            apelido = this.txtCodigoCatalogo.Text,
                            codigoMarca = ((Marca)this.cbxMarca.SelectedValue).codigo,
                            codigoLinha = ((Linha)this.cbxLinha.SelectedValue).codigo,
                            codigoTipo = ((Tipo)this.cbxTipo.SelectedValue).codigo,
                            promocoes = this.promocaoParser.paraObjetos(this.lsbPromocoes)
                        };

    o entity framework esta inserindo o produto e as promoções, quando na verdade eu quero inserir o prouto e vincular ele a uma lista de produtos já cadastrados na base de dados e quando for realizar atualizações qual a forma que devo fazer ? Estou utilizando o entity framework 6 com sql server em um projeto de windows forms  com C#

    Obrigado

    terça-feira, 9 de junho de 2015 22:48

Respostas

  • Junior,

    Não sei exatamente como está modelado seu banco de dados, mas leve em conta que no modelo relacional não existe o conceito de N:N.

    Na prática, a solução para esta questão passa pela criação de uma entidade/tabela associativa. No caso, vc criaria algo como PromocaoProduto, ligando as entidades Produto e Promocao. Desta forma ficaria fácil transpor os dados para o seu banco.

    Espero ter ajudado.

    Abs

    • Sugerido como Resposta CarlosEduardo Ferreira quarta-feira, 10 de junho de 2015 12:47
    • Marcado como Resposta Junior-kun segunda-feira, 15 de junho de 2015 17:28
    quarta-feira, 10 de junho de 2015 12:24

Todas as Respostas

  • Junior,

    Não sei exatamente como está modelado seu banco de dados, mas leve em conta que no modelo relacional não existe o conceito de N:N.

    Na prática, a solução para esta questão passa pela criação de uma entidade/tabela associativa. No caso, vc criaria algo como PromocaoProduto, ligando as entidades Produto e Promocao. Desta forma ficaria fácil transpor os dados para o seu banco.

    Espero ter ajudado.

    Abs

    • Sugerido como Resposta CarlosEduardo Ferreira quarta-feira, 10 de junho de 2015 12:47
    • Marcado como Resposta Junior-kun segunda-feira, 15 de junho de 2015 17:28
    quarta-feira, 10 de junho de 2015 12:24
  • as entidades estão dessa forma :

        [Table("produtos")]
        public class Produto
        {
            [Key]
            public Int64 codigo { get; set; }
    
            [Required]
            public string nome { get; set; }
            
            public decimal preco { get; set; }
    
            [Required]
            public string apelido { get; set; }
    
            public Int64 codigoTipo { get; set; }
            [ForeignKey("codigoTipo")]
            public virtual Tipo tipo {get; set;}
    
            public Int64 codigoLinha { get; set; }
            [ForeignKey("codigoLinha")]
            public virtual Linha linha { get; set; }
    
            public Int64 codigoMarca { get; set; }
            [ForeignKey("codigoMarca")]
            public virtual Marca marca { get; set; }
    
            public virtual IList<Promocao> promocoes { get; set; }
        }

        [Table("promocoes")]
        public class Promocao
        {
            [Key]
            public Int64 codigo { get; set; }
    
            [Required]
            public string nome { get; set; }
    
            
            public float desconto { get; set; }
    
            [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
            public DateTime dataInicio { get; set; }
    
            [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
            public DateTime dataFim { get; set; }
    
            public virtual IList<Produto> produtos { get; set; }
        }
    Então para eu conseguir criar um novo produto e associar uma lista de promoções a este mesmo produto eu vou ter que criar a entidade intermediaria para fazer isso na mão ?
    quarta-feira, 10 de junho de 2015 19:05
  • A solução o Renato Groffe já postou. Crie uma tabela associativa conforme te foi falado. Essa é a melhor forma que eu conheço para trata de relacionamentos N:N, se não for a única. O EF não vai entender como você gostaria. Ele não foi projetado para isso, pois feriria as regras de BD e etc. Desta forma você consegue associar um produto a uma ou mais promoções: Exemplo. Digamos que eu tenha o produto: PD1, PD2 e as promoções: PM1, PM2, PM3, PM4. Essas são as PK's. Na tabela associativa eu poderia ter:

    PD1 >> PM1

    PD1 >> PM2

    PD1 >> PM4

    PD2 >> PM1

    PD2 >> PM3

    E assim sucessivamente. Aí na sua LINQ você pegaria tudo que necessitasse e trabalharia com as informações já cadastradas. Isso foi o que o colega Renato Groffe disse. A resposta é dele, eu apenas exemplifiquei o que ele disse, nada mais.

    quarta-feira, 10 de junho de 2015 19:54
  • Pessoal valeu a força ai e desculpa a demora, estou postado aqui o meu codigo de classe que recebe os Ids das outras classes, deu certo aqui, obrigado

        public class ProdutoPromocao
        {
            [Column(Order = 0),Key]
            public Int64 coigoProduto { get; set; }
            [ForeignKey("coigoProduto")]
            public virtual Produto produto { get; set; }
    
            [Column(Order = 1), Key]
            public Int64 codigoPromocao { get; set; }
            [ForeignKey("codigoPromocao")]
            public virtual Promocao promocao { get; set; }
        }

    segunda-feira, 15 de junho de 2015 17:28
  • Pessoal só para complementar a discussão com outras possíveis soluções do problema achei uma forma de mapear o relacionamento Many to Many sem a necessidade da criação da classe associativa somente com os objetos e códigos, mas tive que migrar para a fluent api, segue abaixo uma outra solução para o problema

    Mapeamento da Classe produto:

        public class ProdutoTypeConfiguration : EntityTypeConfiguration<Produto>
        {
            public ProdutoTypeConfiguration()
            {
                ToTable("PRODUTOS");
    
                Property(p => p.Codigo)
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
                    .IsRequired();
    
                Property(p => p.Nome)
                    .HasMaxLength(100)
                    .IsRequired();
    
                Property(p => p.Preco)
                    .HasPrecision(8, 2)
                    .IsRequired();
    
                Property(p => p.Apelido)
                    .HasMaxLength(20)
                    .IsRequired();
    
                HasKey(p => p.Codigo);
    
                HasRequired(p => p.Tipo)
                    .WithMany(p => p.Produtos)
                    .HasForeignKey(fk => fk.CodigoTipo)
                    .WillCascadeOnDelete(false);
    
                HasRequired(p => p.Linha)
                    .WithMany(p => p.Produtos)
                    .HasForeignKey(fk => fk.CodigoLinha)
                    .WillCascadeOnDelete(false);
    
                HasRequired(p => p.Marca)
                    .WithMany(p => p.Produtos)
                    .HasForeignKey(fk => fk.CodigoMarca)
                    .WillCascadeOnDelete(false);
    
                HasMany(p => p.Promocoes)
                    .WithMany(p => p.Produtos)
                    .Map(m =>
                    {
                        m.MapRightKey("codigo_produto");
                        m.MapLeftKey("codigo_promocao");
                        m.ToTable("produtos_promocoes");
                    });
    
            }
        }

    mapeamento da classe promoção:

        public class PromocaoTypeConfiguration : EntityTypeConfiguration<Promocao>
        {
            public PromocaoTypeConfiguration()
            {
                ToTable("Promocoes");
    
                Property(p => p.Codigo)
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
                    .IsRequired();
    
                Property(p => p.Nome)
                    .HasMaxLength(100)
                    .IsRequired();
    
                Property(p => p.Desconto)
                    .HasPrecision(8, 2)
                    .IsRequired();
    
                Property(p => p.DataInicio);
    
                Property(p => p.DataInicio);
    
    
                HasKey(p => p.Codigo);
    
            }
        }

    quarta-feira, 1 de julho de 2015 05:18