none
Como Mapear com o EntityFramework e Fluent API tabelas com relacionamento Agregação. RRS feed

  • Pergunta

  • Olá companheiros.

    Tenho Uma tabela PESSOA e PESSOAFISICA.

    Quando compilo minha aplicação Code-First, o EntityFramework não consegue criar o banco... Acedito que seja um erro na implementação das classes com o relacionamento Agregacao.... Alguém sabe como me ajudar?

    Abaixo segue como estou mapeando...

    //Classe Pessoa

     public class PessoaModel
        {
            public int PessoaId { get; set; }
            public int PessoaTipoId { get; set; }
            public DateTime DataInclusao { get; set; }
    
    
            public virtual PessoaFisicaModel PessoaFisicaModel { get; set; }
        }

    //Classe PessoaFisica

     public class PessoaFisicaModel
        {
            public int PessoaId { get; set; }
            public string NomeCompleto { get; set; }
            public string Apelido { get; set; }
           
            public virtual PessoaModel PessoaModel { get; set; }
    
        }

    //Classe Configuracao Pessoa

    class PessoaEntities : EntityTypeConfiguration<PessoaModel>
        {
            public PessoaEntities()
            {
                ToTable("tbPessoa");
                HasKey(c => c.PessoaId);
    
                Property(c => c.PessoaId)
                   .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    
                Property(c => c.DataInclusao).HasColumnName("DataInclusao")
                    .HasColumnType("DateTime")
                    .IsRequired();
            }

    //Classe Configuracao PessoaFisica

    class PessoaFisicaEntities : EntityTypeConfiguration<PessoaFisicaModel>
        {
            public PessoaFisicaEntities()
            {
                ToTable("tbPessoaFisica");
    
                Property(c => c.NomeCompleto).HasColumnName("NomeCompleto")
                    .HasColumnType("Varchar")
                    .HasMaxLength(100)
                    .IsRequired();
                Property(c => c.Apelido).HasColumnName("Apelido")
                   .HasColumnType("Varchar")
                   .HasMaxLength(100)
                   .IsRequired();
    
            }
        }

    quarta-feira, 19 de outubro de 2016 23:29

Respostas

  • Olá Jalber,

    Primeiramente, suas models não estão aproveitando as convenções que o entity traz.

    Antes de mais nada recomendo dar uma lida nesse artigo aqui: https://msdn.microsoft.com/en-us/data/jj679962%28v=vs.113%29.aspx?f=255&MSPPError=-2147217396

    Pois bem, pelo que observei você quer utilizar as convenções do Entity (criar PK sem ter que definir isso manualmente, etc etc)

    A primeira coisa a fazer seria mudar o nome da suas Models. Não vejo necessidade de colocar o nome "PessoaModel" sendo que sabemos o que ela é, portanto seria apenas "Pessoa". A mesma coisa com a "PessoaFisicaModel", ficaria "PessoaFisica". Apenas fazendo isso, muitas coisas já irão ser simplificadas. Analise o raciocínio:

    A convenção diz que uma propriedade definida com o nome "ID" ou nome da classe + "ID" já será considerada uma PK e se ela for do tipo GUID ou numérica, já será identity (auto-incremental).

    No seu caso, você estava definindo o nome da classe como "PessoaModel" e o nome da propriedade como "PessoaId", logo a condição não era atendida para criar a chave sem defini-la explicitamente.

    Outro ponto é na classe "PessoaFisica" que você tem uma propriedade "PessoaId" e precisa que ela seja PK e ForeignKey ao mesmo tempo. Então nessa relação entre Pessoa e PessoaFisica teremos uma relação One-to-One. Para isso é preciso deixar isso explícito na sua classe de configuração. Será necessário adicionar:

    HasKey(c => c.PessoaId);
    
    HasRequired(c => c.Pessoa)
         .WithRequiredDependent(c => c.PessoaFisica);

    Resumindo, suas classes ficarão da seguinte forma:

        public class Pessoa
        {
            public int PessoaId { get; set; }
            public int PessoaTipoId { get; set; }
            public DateTime DataInclusao { get; set; }
    
    
            public virtual PessoaFisica PessoaFisica { get; set; }
        }
    
        public class PessoaFisica
        {
            public int PessoaId { get; set; }
            public string NomeCompleto { get; set; }
            public string Apelido { get; set; }
    
            public virtual Pessoa Pessoa { get; set; }
    
        }
    
        class PessoaEntities : EntityTypeConfiguration<Pessoa>
        {
            public PessoaEntities()
            {
                ToTable("tbPessoa");
    
                Property(c => c.PessoaId)
                   .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    
                Property(c => c.DataInclusao).HasColumnName("DataInclusao")
                    .HasColumnType("DateTime")
                    .IsRequired();
            }
    
        }
    
        class PessoaFisicaEntities : EntityTypeConfiguration<PessoaFisica>
        {
            public PessoaFisicaEntities()
            {
                ToTable("tbPessoaFisica");
                HasKey(c => c.PessoaId);
    
                HasRequired(c => c.Pessoa)
                    .WithRequiredDependent(c => c.PessoaFisica);
    
                Property(c => c.NomeCompleto).HasColumnName("NomeCompleto")
                    .HasColumnType("Varchar")
                    .HasMaxLength(100)
                    .IsRequired();
                Property(c => c.Apelido).HasColumnName("Apelido")
                   .HasColumnType("Varchar")
                   .HasMaxLength(100)
                   .IsRequired();
    
            }
        }

    E seu contexto, algo baseado nesse modelo:

        class PessoaContext : DbContext
        {
            public PessoaContext()
                : base("DefaultConnectionString")
            {
            }
            protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
            {
                modelBuilder.Configurations.Add(new PessoaEntities());
                modelBuilder.Configurations.Add(new PessoaFisicaEntities());
                base.OnModelCreating(modelBuilder);
            }
    
    
            public DbSet<Pessoa> Pessoa { get; set; }
            public DbSet<PessoaFisica> PessoaFisica { get; set; }
    
        }

    Dessa forma seu banco será modelado da forma correta.

    Espero ter ajudado!

    Valeu!


    Se a resposta for relevante ou tenha resolvido seu problema, marque como útil/resposta!

    André Secco
    Microsoft MSP & MSDN Tech Advisor
    Blog: http://andresecco.com.br
    GitHub: http://github.com/andreluizsecco
    Twitter: @andre_secco



    • Editado André SeccoMVP quinta-feira, 20 de outubro de 2016 18:56
    • Sugerido como Resposta André SeccoMVP quinta-feira, 20 de outubro de 2016 18:57
    • Marcado como Resposta JR-Master quinta-feira, 20 de outubro de 2016 21:40
    quinta-feira, 20 de outubro de 2016 10:59

Todas as Respostas

  • Olá Jalber,

    Primeiramente, suas models não estão aproveitando as convenções que o entity traz.

    Antes de mais nada recomendo dar uma lida nesse artigo aqui: https://msdn.microsoft.com/en-us/data/jj679962%28v=vs.113%29.aspx?f=255&MSPPError=-2147217396

    Pois bem, pelo que observei você quer utilizar as convenções do Entity (criar PK sem ter que definir isso manualmente, etc etc)

    A primeira coisa a fazer seria mudar o nome da suas Models. Não vejo necessidade de colocar o nome "PessoaModel" sendo que sabemos o que ela é, portanto seria apenas "Pessoa". A mesma coisa com a "PessoaFisicaModel", ficaria "PessoaFisica". Apenas fazendo isso, muitas coisas já irão ser simplificadas. Analise o raciocínio:

    A convenção diz que uma propriedade definida com o nome "ID" ou nome da classe + "ID" já será considerada uma PK e se ela for do tipo GUID ou numérica, já será identity (auto-incremental).

    No seu caso, você estava definindo o nome da classe como "PessoaModel" e o nome da propriedade como "PessoaId", logo a condição não era atendida para criar a chave sem defini-la explicitamente.

    Outro ponto é na classe "PessoaFisica" que você tem uma propriedade "PessoaId" e precisa que ela seja PK e ForeignKey ao mesmo tempo. Então nessa relação entre Pessoa e PessoaFisica teremos uma relação One-to-One. Para isso é preciso deixar isso explícito na sua classe de configuração. Será necessário adicionar:

    HasKey(c => c.PessoaId);
    
    HasRequired(c => c.Pessoa)
         .WithRequiredDependent(c => c.PessoaFisica);

    Resumindo, suas classes ficarão da seguinte forma:

        public class Pessoa
        {
            public int PessoaId { get; set; }
            public int PessoaTipoId { get; set; }
            public DateTime DataInclusao { get; set; }
    
    
            public virtual PessoaFisica PessoaFisica { get; set; }
        }
    
        public class PessoaFisica
        {
            public int PessoaId { get; set; }
            public string NomeCompleto { get; set; }
            public string Apelido { get; set; }
    
            public virtual Pessoa Pessoa { get; set; }
    
        }
    
        class PessoaEntities : EntityTypeConfiguration<Pessoa>
        {
            public PessoaEntities()
            {
                ToTable("tbPessoa");
    
                Property(c => c.PessoaId)
                   .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    
                Property(c => c.DataInclusao).HasColumnName("DataInclusao")
                    .HasColumnType("DateTime")
                    .IsRequired();
            }
    
        }
    
        class PessoaFisicaEntities : EntityTypeConfiguration<PessoaFisica>
        {
            public PessoaFisicaEntities()
            {
                ToTable("tbPessoaFisica");
                HasKey(c => c.PessoaId);
    
                HasRequired(c => c.Pessoa)
                    .WithRequiredDependent(c => c.PessoaFisica);
    
                Property(c => c.NomeCompleto).HasColumnName("NomeCompleto")
                    .HasColumnType("Varchar")
                    .HasMaxLength(100)
                    .IsRequired();
                Property(c => c.Apelido).HasColumnName("Apelido")
                   .HasColumnType("Varchar")
                   .HasMaxLength(100)
                   .IsRequired();
    
            }
        }

    E seu contexto, algo baseado nesse modelo:

        class PessoaContext : DbContext
        {
            public PessoaContext()
                : base("DefaultConnectionString")
            {
            }
            protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
            {
                modelBuilder.Configurations.Add(new PessoaEntities());
                modelBuilder.Configurations.Add(new PessoaFisicaEntities());
                base.OnModelCreating(modelBuilder);
            }
    
    
            public DbSet<Pessoa> Pessoa { get; set; }
            public DbSet<PessoaFisica> PessoaFisica { get; set; }
    
        }

    Dessa forma seu banco será modelado da forma correta.

    Espero ter ajudado!

    Valeu!


    Se a resposta for relevante ou tenha resolvido seu problema, marque como útil/resposta!

    André Secco
    Microsoft MSP & MSDN Tech Advisor
    Blog: http://andresecco.com.br
    GitHub: http://github.com/andreluizsecco
    Twitter: @andre_secco



    • Editado André SeccoMVP quinta-feira, 20 de outubro de 2016 18:56
    • Sugerido como Resposta André SeccoMVP quinta-feira, 20 de outubro de 2016 18:57
    • Marcado como Resposta JR-Master quinta-feira, 20 de outubro de 2016 21:40
    quinta-feira, 20 de outubro de 2016 10:59
  • Funcionou perfeitamente André!!!

    Não sei como te agradecer companheiro. Vc é muito inteligente!!!

    Muito obrigado :)

    quinta-feira, 20 de outubro de 2016 21:40