我可以在Entity Framework 6 - Update-Database命令的种子方法操作中使用foreach循环

时间:2015-08-26 17:06:42

标签: c# entity-framework

主要是我试图使用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”

     

更新条目时发生错误。有关详细信息,请参阅内部异常。

3 个答案:

答案 0 :(得分:1)

就像@Sirwan所说,你看到的异常是告诉你你违反了state表的外键约束。根据FK名称判断,您看起来使用stateId表中不存在的States

  

在表格上插入或更新" City"违反外键约束" FK_public.City_public.States_StateId

你也说过:

  

State Id是来自States Table的外键

所以,我假设States表是一个预先填充的表,其中已经有状态记录。换句话说,没有基于XML文件插入状态。是这样的吗?

您的代码也有两个主要假设:

  1. 它假定Uf枚举中的项目数小于或等于States表中的记录数。

  2. 它假定Uf枚举中的项目的排序与States表中按StatedId升序排序的记录相匹配。

  3. 如果假设1无效,即Uf枚举中的记录多于States表中的记录,则会尝试使用不存在的stateId插入记录

    如果假设2无效,即Uf枚举元素未按stateId表中的States排序,则会将城市插入错误的状态。

    根据您发布的例外情况,我打赌假设1无效,Uf枚举上的记录数与States表中的记录数不匹配。或者,另一个选项是StateId表中的States值与枚举中元素的原始数量不匹配。

    例如,我看到你来自巴西,我们有27个州。这里我们有三个错误选项:

    1. States表没有全部27个州
    2. StateId表中的States值不是从1开始
    3. StateId表格中的States值不是连续的,即它们不会从1-27开始,但有以下差距:1,2,3,6,7,8,9 ...
    4. 在上述所有情况中,您的代码最终会使用违反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++;
    }