Entity Framework Relationship Error

Asked

Viewed 588 times

1

I am developing a test project that I intend to include in my TCC, but I found a problem when relating two entities to create the Tablas in the database with the Entity Framework. Are they 'Post' and 'Comment'

   public class Post
    {
        public Post()
        {
            DataPost = DateTime.Now;
            Categoria = new Categoria();
            Comentarios = new List<Comentario>();
        }

        public int PostId { get; set; }

        public string TituloPost { get; set; }

        public string SubTituloPost { get; set; }

        public DateTime DataPost { get; set; }

        //Post obrigatoriamente tem uma categoria
        public virtual Categoria Categoria { get; set; }

        //Post tem 0 ou vários comentários
        public virtual ICollection<Comentario> Comentarios { get; set; } //=====Comentários

        public override string ToString()
        {
            return TituloPost;
        }
    }

class Comment

    public class Comentario
    {
        public Comentario()
        {
            DataComentario = DateTime.Now;
            Post = new Post();
        }

        public int ComentarioId { get; set; }

        public DateTime DataComentario { get; set; }

        public string DescricaoComentario { get; set; }

        //1 Cometário pertence somente a 1 Post
        public virtual Post Post { get; set; } //=============Post

        public override string ToString()
        {
            return DescricaoComentario;
        }
    }

category class

public class Categoria
{
    public Categoria()
    {
        Ativa = true;
        Posts = new List<Post>();
    }

    public int CategoriaId { get; set; }

    public string DescricaoCategoria { get; set; }

    public bool Ativa { get; set; }

    //Categoria tem uma coleção de Post
    public virtual ICollection<Post> Posts { get; set; }

    public override string ToString()
    {
        return DescricaoCategoria;
    }

}

I tried to do the mapping in various ways as presented in this post..: http://netcoders.com.br/mapeamento-com-entity-framework-code-first-fluent-api-parte-2/ Part 2.

But in every way I tried it creates the tables the way I need, and I can even insert the Post, but when I insert a comment it gives a relationship error.

Who can help me I thank.

Edit

MAPPING

public class MapPost : EntityTypeConfiguration<Post>
{
    public MapPost()
    {
        ToTable("Post");
        HasKey(x => x.PostId);
        Property(x => x.TituloPost).HasMaxLength(150).IsRequired();
        Property(x => x.SubTituloPost).HasMaxLength(300).IsRequired();
        Property(x => x.DataPost).IsRequired();

        HasRequired(p => p.Categoria)
            .WithMany(c => c.Posts)
            .Map(c => c.MapKey("CategoriaId"));
    }
}


public class MapCategoria : EntityTypeConfiguration<Categoria>
{
    public MapCategoria()
    {
        ToTable("Categoria");
        HasKey(i => i.CategoriaId);
        Property(d => d.DescricaoCategoria).HasMaxLength(60).IsRequired();
    }
}



public class MapComentario : EntityTypeConfiguration<Comentario>
{
    public MapComentario()
    {
        ToTable("Comentario");
        HasKey(i => i.ComentarioId);
        Property(d => d.DataComentario).IsRequired();
        Property(d => d.DescricaoComentario).IsRequired();

        HasRequired(x => x.Post)
            .WithMany(c => c.Comentarios)
            .Map(x => x.MapKey("fk_PostId"));
    }
}

CONTEXT

public class Context : DbContext
{
    public Context() : base ("ConnectionString")
    {
        Configuration.LazyLoadingEnabled = false;
        Configuration.ProxyCreationEnabled = false;
    }

    public DbSet<Categoria> Categoria { get; set; }

    public DbSet<Post> Post { get; set; }

    public DbSet<Comentario> Comentario { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
        modelBuilder.Properties<string>().Configure(p => p.HasColumnType("varchar"));

        modelBuilder.Configurations.Add(new Map.MapPost());
        modelBuilder.Configurations.Add(new Map.MapCategoria());
        modelBuilder.Configurations.Add(new Map.MapComentario());

        base.OnModelCreating(modelBuilder);
    }
}

ENTERING DATA

        var post = new Post
        {
             TituloPost = "Titulo Post 02",
             SubTituloPost = "SubTitulo Post 02",
             Categoria = new Categoria
             {
                   DescricaoCategoria = "Categoria de Teste 02",
                   Ativa = true,
             },
             Comentarios = new List<Comentario>
             {
                 new Comentario
                 {
                     DescricaoComentario = "Comentário Teste 01",
                     DataComentario = DateTime.Now
                 },

                 new Comentario
                 {
                     DescricaoComentario = "Comentário Teste 02",
                     DataComentario = DateTime.Now
                 },

                 new Comentario
                 {
                     DescricaoComentario = "Comentário Teste 03",
                     DataComentario = DateTime.Now
                 }
             }
        };
        db.Post.Add(post);
        if (!db.GetValidationErrors().Any())
        {
            db.SaveChanges();
        }

ERROR

inserir a descrição da imagem aqui

OBSERVATION

The database I’m using is Mysql.

  • 2

    What’s the mistake?....

  • Within the builder of Comentario you’re doing it Post = new Post();. Take it off. The same goes for the builder of Post, take that line Categoria = new Categoria();. I’m not sure that’s it because I haven’t seen how you’re trying to add to DbContext before calling the SaveChanges, but try it there.

  • I see a title like that question, it makes me want to suggest taking flowers next time.

  • Put the code you are using to save, and the error message.

  • @Virgilionovic I edited the publication with new information and error.

  • @Alisson I got to comment on these lines of code in the constructors and even then error occurred.

  • @Cassioalves I put the code and the error message.

Show 2 more comments

1 answer

0


Friend, see if this helps you, as this code below as soon as you perform the Migration for the database the tables will be created as follows.

Banco de Dados realizado a migration Code-First

Classes

public class Pais
{
    public Pais()
    {
        Estados = new List<Estado>();
    }    

    public int Handle{ get; set; }
    public string Nome { get; set; }
    public string Sigla { get; set; }
    public IEnumerable<Estado> Estados { get; set; }      
}

public class Estado : EntityBase
{
    public Estado()
    {
        Cidades = new List<Cidade>();
    }     

    public int Handle{ get; set; }
    public string Nome { get; set; }
    public string Sigla { get; set; }
    public long PaisHandle { get; set; }
    public Pais Pais { get; set; }
    public IEnumerable<Cidade> Cidades { get; set; }  
}

public class Cidade
{
    public Cidade() 
    {

    }
    public int Handle{ get; set; }
    public string Nome { get; set; }
    public string Sigla { get; set; }
    public long EstadoHandle { get; set; }
    public Estado Estado { get; set; }        
}

Mapping the Entities

public class PaisMap : EntityTypeConfiguration<Pais>
{
    public PaisMap()
    {
        ToTable("PAIS");

        HasKey(x => x.Handle);

        Property(x => x.Handle)
            .HasColumnName("HANDLE")
            .HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);

        Property(x => x.Nome)
            .IsRequired()
            .HasMaxLength(150)
            .HasColumnName("NOME");

        Property(x => x.Sigla)
            .IsRequired()
            .HasMaxLength(3)
            .HasColumnName("SIGLA");                              
    }

}

public class EstadoMap : EntityTypeConfiguration<Estado>
{
    public EstadoMap()
    {
        ToTable("ESTADO");

        HasKey(x => x.Handle);

        Property(x => x.Handle)
            .HasColumnName("HANDLE")
            .HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);

        Property(x => x.Nome)
            .IsRequired()
            .HasMaxLength(150)
            .HasColumnName("NOME");

        Property(x => x.Sigla)
            .IsRequired()
            .HasMaxLength(2)
            .HasColumnName("SIGLA");

        HasRequired(x => x.Pais)
            .WithMany()
            .HasForeignKey(x => x.PaisHandle);

        Property(x => x.PaisHandle)
            .HasColumnName("PAISHANDLE");
    }
}

public class CidadeMap : EntityTypeConfiguration<Cidade>
{
    public CidadeMap()
    {
        ToTable("CIDADE");

        HasKey(x => x.Handle);

        Property(x => x.Handle)
            .HasColumnName("HANDLE")
            .HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);

        Property(x => x.Nome)
            .IsRequired()
            .HasMaxLength(150)
            .HasColumnName("NOME");

        Property(x => x.Sigla)
            .IsRequired()
            .HasMaxLength(3)
            .HasColumnName("SIGLA");

        HasRequired(x => x.Estado)
            .WithMany()
            .HasForeignKey(x => x.EstadoHandle);

        Property(x => x.EstadoHandle)
            .HasColumnName("ESTADOHANDLE");
    }
}

Context class

public class DataContext : DbContext
{
    public DataContext() : base("name=DefaultConnection")
    {
        Configuration.LazyLoadingEnabled = false;
        Configuration.ProxyCreationEnabled = false;
    }

    public DbSet<Pais> Pais { get; set; }
    public DbSet<Estado> Estado { get; set; }
    public DbSet<Cidade> Cidade { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Aqui vamos remover a pluralização padrão do Etity Framework que é em inglês
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        /*Desabilitamos o delete em cascata em relacionamentos 1:N evitando
         ter registros filhos     sem registros pai*/
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

        //Basicamente a mesma configuração, porém em relacionamenos N:N
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

        /*Toda propriedade do tipo string na entidade POCO
         seja configurado como VARCHAR no SQL Server*/

        modelBuilder.Properties<string>()
                  .Configure(p => p.HasColumnType("VARCHAR"));

        modelBuilder.Configurations.Add(new PaisMap());
        modelBuilder.Configurations.Add(new EstadoMap());
        modelBuilder.Configurations.Add(new CidadeMap());            

        base.OnModelCreating(modelBuilder);
    }
}
  • Young man, this has absolutely nothing to do with what you were asked.

  • @LINQ, Of course, his problem is in creating his entities, he’s not putting the ID clunas to reference the FK, so he’s making the mistake. I gave an example to him how the relationships between the entities and how to configure.

  • @Is it necessary to create an identifier for the class? I saw some examples with and without the identifiers in the classes and this way I did it created the foreign keys in the related tables as I expected, but when saving it gives error.

  • @Eliseumarcos, it would be nice for you to search in Datanotations because with it you will see that in the Entity class you configure the table name, the PK field and the FK fields, or you can search for mapping as I did there with the classes Paismap, Estadomap and Cidademap, because you have to define which class is the PK or FK however much it had already created in the database correctly. Run a test according to the code I sent you and see if it’s right.

Browser other questions tagged

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