Fluent Api inserting unwanted records

0

I have the following classes:

Status.cs

public class Estado
{
    public Int32 EstadoId { get; set; }
    public Int32 CodigoEstado { get; set; }
    public String Sigla { get; set; }
    public String Nome { get; set; }
    public virtual ICollection<Cidade> CidadeLista { get; set; }        

    public Estado()
    {
        CidadeLista = new List<Cidade>();
    }
}

City.cs

public class Cidade
{
    public Int32 CidadeId { get; set; }
    public Int32 CodigoEstado { get; set; }
    public Int32 CodigoCidade { get; set; }
    public String Nome { get; set; }

    public Estado Estado { get; set; }
    public virtual ICollection<Endereco> EnderecoLista { get; set; }

    public Cidade()
    {
        EnderecoLista = new List<Endereco>();
    }
}

And the following table mappings:

StatusMap.cs

public class EstadoMap : EntityTypeConfiguration<Estado>
{
    public EstadoMap()
    {
        ToTable("ESTADO");
        HasKey(x => x.EstadoId);

        Property(x => x.EstadoId)
            .HasColumnName("ESTADO_ID")
            .HasColumnOrder(0)
            .IsRequired();

        Property(x => x.CodigoEstado)
            .HasColumnName("CODIGO_ESTADO")
            .HasColumnOrder(1)
            .IsRequired();

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

        Property(x => x.Nome)
            .HasColumnName("NOME")
            .HasColumnOrder(3)
            .IsRequired()
            .HasMaxLength(30);
    }
}

CidadeMap.cs

public class CidadeMap : EntityTypeConfiguration<Cidade>
{
    public CidadeMap()
    {
        ToTable("CIDADE");
        HasKey(x => x.CidadeId);

        Property(x => x.CidadeId)
            .HasColumnName("CIDADE_ID");

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

        Property(x => x.CodigoCidade)
            .HasColumnName("CODIGO_CIDADE")
            //.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }))
            .IsRequired();

        Property(x => x.CodigoEstado)
            .HasColumnName("CODIGO_ESTADO")

            .IsRequired();

        //Relationships
        HasRequired(x => x.Estado)
            .WithMany(x => x.CidadeLista)
            .HasForeignKey(x => x.CodigoEstado);
    }
}

I looked in the database and the result is as expected, the column codigo_estado of table Estado referenced in table Cidade as FK.

To populate them, I saved the IBGE pages with this information in my machine and then fed the tables, as per the code below.

CitySeed

public class CidadeSeed
{
    public static void Seed(TecGasContext context)
    {
        List<Estado> listaEstado = new List<Estado>()
        {
            new Estado {CodigoEstado = 12, Nome = "Acre", Sigla = "AC" },
            new Estado {CodigoEstado = 27, Nome = "Alagoas", Sigla = "AL" },
            new Estado {CodigoEstado = 13, Nome = "Amazonas", Sigla = "AM" },
            new Estado {CodigoEstado = 16, Nome = "Amapá", Sigla = "AP" },
            new Estado {CodigoEstado = 29, Nome = "Bahia", Sigla = "BA" },
            new Estado {CodigoEstado = 23, Nome = "Ceará", Sigla = "CE" },
            new Estado {CodigoEstado = 53, Nome = "Distrito Federal", Sigla = "DF" },
            new Estado {CodigoEstado = 32, Nome = "Espírito Santo", Sigla = "ES" },
            new Estado {CodigoEstado = 52, Nome = "Goiás", Sigla = "GO" },
            new Estado {CodigoEstado = 21, Nome = "Maranhão", Sigla = "MA" },
            new Estado {CodigoEstado = 31, Nome = "Minas Gerais", Sigla = "MG" },
            new Estado {CodigoEstado = 50, Nome = "Mato Grosso do Sul", Sigla = "MS" },
            new Estado {CodigoEstado = 51, Nome = "Mato Grosso", Sigla = "MT" },
            new Estado {CodigoEstado = 15, Nome = "Pará", Sigla = "PA" },
            new Estado {CodigoEstado = 25, Nome = "Paraíba", Sigla = "PB" },
            new Estado {CodigoEstado = 26, Nome = "Pernambuco", Sigla = "PE" },
            new Estado {CodigoEstado = 22, Nome = "Piauí", Sigla = "PI" },
            new Estado {CodigoEstado = 41, Nome = "Paraná", Sigla = "PR" },
            new Estado {CodigoEstado = 33, Nome = "Rio de Janeiro", Sigla = "RJ" },
            new Estado {CodigoEstado = 24, Nome = "Rio Grande do Norte", Sigla = "RN" },
            new Estado {CodigoEstado = 11, Nome = "Rondônia", Sigla = "RO" },
            new Estado {CodigoEstado = 14, Nome = "Roraima", Sigla = "RR" },
            new Estado {CodigoEstado = 43, Nome = "Rio Grande do Sul", Sigla = "RS" },
            new Estado {CodigoEstado = 42, Nome = "Santa Catarina", Sigla = "SC" },
            new Estado {CodigoEstado = 28, Nome = "Sergipe", Sigla = "SE" },
            new Estado {CodigoEstado = 35, Nome = "São Paulo", Sigla = "SP" },
            new Estado {CodigoEstado = 17, Nome = "Tocantis", Sigla = "TO" },
        };


        foreach (var estadoItem in listaEstado)
        {
            var client = new WebClient();
            var content = client.DownloadString(String.Format("{0}{1}{2}", "file:///C:/Projetos/TecGas/CidadesPorEstado/", estadoItem.Sigla, ".html"));

            byte[] bytes = Encoding.Default.GetBytes(content);
            content = Encoding.UTF8.GetString(bytes);

            var document = new HtmlDocument();
            document.LoadHtml(content);

            var htmlContainer =
                    document.DocumentNode.SelectNodes("html/body/div[@id='conteudo']/table[@id='municipios']/tbody/tr");

            foreach (var cidadeItem in htmlContainer)
            {
                var codigoEstado = estadoItem.CodigoEstado;
                Int32 codigoCidade = Convert.ToInt32(cidadeItem.SelectSingleNode("td[@class='codigo']").InnerText);
                var nome = cidadeItem.SelectSingleNode("td[@class='nome']").InnerText;
                Cidade novaCidade = new Cidade
                {
                    CodigoEstado = codigoEstado,
                    CodigoCidade = codigoCidade,
                    Nome = nome,
                    Estado = estadoItem
                };

                try
                {
                    context.Configuration.LazyLoadingEnabled = false;
                    context.Cidade.Add(novaCidade);
                    context.SaveChanges();
                }
                catch (DbEntityValidationException e)
                {
                    StreamWriter writer = new StreamWriter(@"C:\Projetos\TecGas\CidadesPorEstado\Erro.txt");
                    foreach (var eve in e.EntityValidationErrors)
                    {
                        writer.Write(String.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", eve.Entry.Entity.GetType().Name, eve.Entry.State));

                        foreach (var ve in eve.ValidationErrors)
                        {
                            writer.Write(String.Format("- Property: \"{0}\", Error: \"{1}\"",
                                ve.PropertyName, ve.ErrorMessage));
                        }
                    }
                    writer.Close();
                    throw;
                }
            }
        }
    }
}

Configuration.cs

internal sealed class Configuration : DbMigrationsConfiguration<TecGas.BackEnd.DataAccess.TecGasContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }

    protected override void Seed(TecGasContext context)
    {
        CidadeSeed.Seed(context);
    }
}

In the Estado table everything is ok, the fields entered are exactly the ones I fed the table with. In the Cidade table, the codigo_estado FK is being fed with the EstadoId column. It's not what I want. I would like Cidade to store as a reference not the id of estado but its code. When I run tests, I stopped exactly where the codigo_estado field of the Cidade table is fed and the value passed is exactly the desired one, but after SaveChanges() when I look in the database I see that there is another value there.

Can you help me find what I'm doing wrong?

Thank you!

    
asked by anonymous 26.08.2016 / 21:14

1 answer

2

In this mapping:

 HasRequired(x => x.Estado)
            .WithMany(x => x.CidadeLista)
            .HasForeignKey(x => x.CodigoEstado);

You are saying in which field of the Cidade table you are writing the id of Estado , because there logic says that if it is a reference, it has to be the id of the table estado .

If it is a field other than FK then you can fill it manually.

Just a suggestion: leave the code below outside loop :

context.Configuration.LazyLoadingEnabled = false;
context.Cidade.AddRange(novaListaCidade);
context.SaveChanges();

I would use AddRange , or at least leave only the Add within the loop and the SaveChanges() out of loop . This would increase performance and if at some insert issue occur problem would rollback at all automatically.

    
27.08.2016 / 03:26