Mainly I'm trying to insert all cities data coming from an Xml using a foreach loop to iterate through each state. We have more than 5000 city records, and this was the only approach I could come up with.
// Cities Seeding foreach (var uf in Enum.GetValues(typeof(Uf))) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load("http://servicos.cptec.inpe.br/~rserv/estados/cidade-" + uf.ToString() + ".xml"); int cityId = Convert.ToInt32(xmlDoc.SelectSingleNode("/climas/clima/estados/estado/cidades/cidade").Attributes["id"].Value); string cityName = xmlDoc.SelectSingleNode("/climas/clima/estados/estado/cidades/cidade").Attributes["nome"].Value.ToString(); bool capital = Convert.ToBoolean(xmlDoc.SelectSingleNode("/climas/clima/estados/estado/cidades/cidade").Attributes["capital"].Value); int stateId = 1; //if (!capital) //{ context.Cities.AddOrUpdate( c => c.CityId, new City { CityId = cityId, CityName = cityName, StateId = stateId }); //} //else //{ //context.Capitals.AddOrUpdate( // cp => cp.CityId, // new Capital // { // CityId = cityId, // CityName = cityName, // StateId = stateId // }); //} stateId++; }
I'm not sure if makes any difference in this case but, State Id is a foreign key from States Table.
This is my error message:
System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.Entity.Core.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Npgsql.NpgsqlException: ERROR: 23503: insert or update on table "City" violates foreign key constraint "FK_public.City_public.States_StateId"
An error occurred while updating the entries. See the inner exception for details.
Like @Sirwan said, the exception you are seeing is telling you that you are violating the foreign key constraint to the states table. Judging by the FK name, it looks like you are using a stateId
value that doesn't exist in the States
table
insert or update on table "City" violates foreign key constraint "FK_public.City_public.States_StateId
You also said:
State Id is a foreign key from States Table
So, I'm assuming that the States table is a pre-populated table with the state records already in it. In other words, the states are not being inserted based on the XML file. Is that the case?
Your code also makes two main assumptions:
It assumes that the number of items in the Uf
enum is less than or equal to the number of records in the States
table.
It assumes that the items in the Uf
enum are sorted matching the records in the States
table sorted by StatedId
ascending.
If assumption 1 is invalid, ie you have more records in the Uf
enum than you have in the States
table, you will try to insert records using a stateId that doesn't exist.
if assumption 2 is invalid, ie the Uf
enum elements are not sorted matching the stateId
in the States
table, you will insert the cities to the wrong state.
Based on the exception you posted, I bet that assumption 1 is invalid, that the number of records on the Uf
enum doesn't match the number of records in the States
table. Or, the other option is that the StateId
values in the States
table doesn't match the raw number of elements in the enum.
For example, I saw that you are from Brasil, where we have 27 states. Here we have three options for your error:
States
table doesn't have all the 27 states StateId
values in the States
table don't start from 1 StateId
values in the States
table are not contiguous, ie they don't go from 1-27 but have gaps like : 1,2,3,6,7,8,9 ...
In all the scenarios above, your code would end up using an invalid stateId
that will violate the FK constraint.
The less brittle way to write this code, while possibly paying a small performance tax, would be iterate over the values of the State
table instead of using the Uf
enum. That way, you can make sure that the StateId
value that you are assigning to the record matches the one from the table:
foreach (var state in context.States)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://servicos.cptec.inpe.br/~rserv/estados/cidade-" + state.Name + ".xml");
int cityId = Convert.ToInt32(xmlDoc.SelectSingleNode("/climas/clima/estados/estado/cidades/cidade").Attributes["id"].Value);
string cityName = xmlDoc.SelectSingleNode("/climas/clima/estados/estado/cidades/cidade").Attributes["nome"].Value.ToString();
context.Cities.AddOrUpdate(
c => c.CityId,
new City
{
CityId = cityId,
CityName = cityName,
StateId = state.StateId
});
}
This error is telling you that you are violating the foreign key constraint. Check that there is not existing data in the database that is conflicting with the FK constraint causing the creation to fail.
One more thing : Why do you increment the stateId
? As you mentioned you have more than 5000 city records, So the State table must contains more than records too.
This is how my code looked in the end:
context.SaveChanges();
//Cities Seeding
int stateId = 1;
foreach (var uf in Enum.GetValues(typeof(Uf)))
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://servicos.cptec.inpe.br/~rserv/estados/cidade-" + uf.ToString() + ".xml");
XmlElement root = xmlDoc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("/climas/clima/estados/estado/cidades/cidade");
foreach (XmlNode node in nodes)
{
int cityId = Convert.ToInt32(node.Attributes["id"].Value);
string cityName = node.Attributes["nome"].Value.ToString();
bool cityIsCapital = Convert.ToBoolean(node.Attributes["capital"].Value);
context.Cities.AddOrUpdate(
c => c.CityId,
new City()
{
CityId = cityId,
CityName = cityName,
CityIsCapital = cityIsCapital,
StateId = stateId
});
}
stateId++;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.