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!