主要是我试图使用foreach循环插入来自Xml的所有城市数据来迭代每个状态。 我们有超过5000个城市记录,这是我能想到的唯一方法。
refreshCallBack()
我不确定在这种情况下是否有任何区别,但State Id是来自States Table的外键。
这是我的错误消息:
System.Data.Entity.Infrastructure.DbUpdateException:更新条目时发生错误。有关详细信息,请参阅内部异常---> System.Data.Entity.Core.UpdateException:更新条目时发生错误。有关详细信息,请参阅内部异常---> Npgsql.NpgsqlException:错误:23503:在表“City”上插入或更新违反外键约束“FK_public.City_public.States_StateId”
更新条目时发生错误。有关详细信息,请参阅内部异常。
答案 0 :(得分:1)
就像@Sirwan所说,你看到的异常是告诉你你违反了state表的外键约束。根据FK名称判断,您看起来使用stateId
表中不存在的States
值
在表格上插入或更新" City"违反外键约束" FK_public.City_public.States_StateId
你也说过:
State Id是来自States Table的外键
所以,我假设States表是一个预先填充的表,其中已经有状态记录。换句话说,没有基于XML文件插入状态。是这样的吗?
您的代码也有两个主要假设:
它假定Uf
枚举中的项目数小于或等于States
表中的记录数。
它假定Uf
枚举中的项目的排序与States
表中按StatedId
升序排序的记录相匹配。
如果假设1无效,即Uf
枚举中的记录多于States
表中的记录,则会尝试使用不存在的stateId插入记录
如果假设2无效,即Uf
枚举元素未按stateId
表中的States
排序,则会将城市插入错误的状态。
根据您发布的例外情况,我打赌假设1无效,Uf
枚举上的记录数与States
表中的记录数不匹配。或者,另一个选项是StateId
表中的States
值与枚举中元素的原始数量不匹配。
例如,我看到你来自巴西,我们有27个州。这里我们有三个错误选项:
States
表没有全部27个州StateId
表中的States
值不是从1开始StateId
表格中的States
值不是连续的,即它们不会从1-27开始,但有以下差距:1,2,3,6,7,8,9 ...
在上述所有情况中,您的代码最终会使用违反FK约束的无效stateId
。
编写此代码的不那么脆弱的方式,虽然可能需要支付少量的性能税,但是会迭代State
表的值,而不是使用Uf
枚举。这样,您可以确保分配给记录的StateId
值与表中的值匹配:
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
});
}
答案 1 :(得分:0)
此错误告诉您违反了外键约束。检查数据库中是否存在与FK约束冲突的现有数据,从而导致创建失败。
还有一件事:为什么要增加stateId
?正如您所提到的,您有超过5000个城市记录,因此State表必须包含多个记录。
答案 2 :(得分:0)
这就是我的代码最终的样子:
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++;
}