【问题标题】:Entity Framework - Inserting a Parent and Child model with FK simultaneously实体框架 - 同时使用 FK 插入父模型和子模型
【发布时间】:2019-03-07 23:30:48
【问题描述】:

我有一个使用实体框架的 ASP.NET MVC 应用程序。我已经开发了 2 个模型,使用 SQL Server 2008 R2 数据库的数据库优先(代码)方法。一个模型本质上是父模型,另一个是子模型,其中包含指向父模型的数据库生成列的外键。

伪代码:

CREATE TABLE PARENT
(
    ROWID BIGINT IDENTITY(1,1) NOT NULL,
    VALUE NVARCHAR(255) NOT NULL,

    PRIMARY KEY(ROWID)
);

CREATE TABLE CHILD
(
    ROWID BIGINT IDENTITY(1,1) NOT NULL,
    PARENT_ROWID BIGINT NOT NULL,
    VALUE NVARCHAR(255) NOT NULL,

    PRIMARY KEY(ROWID),
    FOREIGN KEY(PARENT_ROWID) REFERENCES PARENT(ROWID)
);

所有这些工作正常,我可以将我的数据绑定到我的模型并编辑字段等等。我的问题是,如果我想为这些模型创建记录,当 CHILD 的外键在 PARENT 中时,如果我同时创建它们,我该怎么做?

所以,我目前的基本步骤是:

  1. 获取要插入数据库的PARENT 模型列表
  2. 插入PARENT 模型
  3. 致电SaveChanges()

    • 对于每个家长:

      1. 为 PARENT 获取 FK
      2. 获取要插入数据库的 CHILD 模型列表
      3. 对于每个 CHILD 模型,插入带有该 FK 的 CHILD
      4. 致电SaveChanges()
  4. 其他模型的其他操作和数据库更新

  5. 致电SaveChanges()

我确信我可以优化它,但这不是我关心的。在我看来,应该有某种方法可以做到这一点,而无需手动查找 FK 或手动设置 FK。如果必须,我可以这样做,但我只想使用一个 SaveChanges() 调用在单个事务中推送这些命令。我正在寻找类似的东西:

  1. 获取要插入数据库的父模型列表

    • 对于每个家长
      1. 插入 PARENT 并返回新的 FK(不保存)
      2. 获取要插入数据库的 CHILD 模型列表
      3. 对于每个 CHILD 模型,插入带有该 FK 的 CHILD
  2. 其他模型对数据库的其他操作和更新

  3. 致电SaveChanges()

为了提供一些上下文,我的实际表中有许多列不能保证是唯一的(这就是 PK 位于 ROWID 上的原因),并且这些行中的每一行都与子表具有一对多关系,其中子表也可能有非唯一的行。不是很理想,但这是我们目前的运营所需要的。我在这里包含了伪代码,因为实际代码是专有的,但如果需要,我可能会创建一个真正的模型。

有什么建议吗?

谢谢

编辑: 因此,我更改了代码以按照建议使用导航属性。这几乎可以工作。这是我的代码:

List<PARENT> parents = getParents();
List<CHILD> children = getChildren();
foreach (PARENT parent in parents)
{
    db.PARENT.add(parent);
    foreach (CHILD child in children)
    {
        child.PARENT = parent;
        db.CHILD.add(child);
    }
}

db.SaveChanges();

乍一看,这正是我想要的。但是,当我运行它时,子记录只会插入第一个父记录。因此,例如,如果我有 3 条 PARENT 记录和 3 条 CHILD 记录,那么我的 CHILD 表中应该有 9 条新记录。但是,在这段代码之后,我只有第一个 PARENT 的 3 条记录。

我假设这与我重复使用相同的子列表并且实体框架以某种方式将它们视为重复的事实有关。我将它移到 PARENT for 循环中,如下所示,它按预期工作:

List<PARENT> parents = getParents();
foreach (PARENT parent in parents)
{
    db.PARENT.add(parent);
    List<CHILD> children = getChildren();
    foreach (CHILD child in children)
    {
        child.PARENT = parent;
        db.CHILD.add(child);
    }
}

db.SaveChanges();

但是,我不希望这样做,因为 getChildren() 函数相当麻烦。有什么想法吗?

【问题讨论】:

    标签: c# entity-framework sql-server-2008


    【解决方案1】:

    我使用以下代码为国家/地区表播种初始 dB 值,其中包含城市、地区、社区及其在一个 dB 调用内的转换。

    您可以实现类似的结构以在同一个 dB 调用中创建父 -> 子 -> 孙实体;

                var country = new MyCountry {
                    Title ="Syria",
                    ShortName="SYR",
                     Translations=new[]
                     {
                         new CountryTranslate { LCID=1, Name="سوريا" },
                         new CountryTranslate { LCID=31, Name="Suriye" },
                         new CountryTranslate {LCID=9, Name="Syria" }
                     },
                      Cities=new[]
                      {
                          new MyCity
                          {
                              Title="Lattakia",
                              ShortName = "LAT",
                              Translations=new[]
                              {
                                  new CityTranslate { LCID=1, Name="اللاذقية" },
                                  new CityTranslate {LCID=31, Name="Lazkiye" },
                                  new CityTranslate {LCID=9, Name="Lattakia" }
                              },
                              Districts=new[]
                              {
                                  new MyDistrict
                                  {
                                      Title="Owineh",
                                      Translations=new[]
                                      {
                                          new DistrictTranslate { LCID=1, Name="العوينة" },
                                          new DistrictTranslate { LCID=31, Name="Uveyne" },
                                          new DistrictTranslate {LCID=9, Name="Owineh" }
                                      },
                                      Neighborhoods = new[]
                                      {
                                          new MyNeighborhood
                                          {
                                              Title="Reji",
                                              Translations = new[]
                                              {
                                                  new NeighborhoodTranslate { LCID=1, Name="الريجي"},
                                                  new NeighborhoodTranslate { LCID=31, Name="Eski Reji"},
                                                  new NeighborhoodTranslate { LCID=9, Name="Old Reji"}
                                              }
                                          }
                                      }
                                  }
                              }
                          }
                      }
                }
    
    context.SaveChanges();
    

    【讨论】:

      【解决方案2】:

      使用导航属性;将“Child.Parent”导航属性设置为尚未保存的“父”实体,EF 将通过一次调用“SaveChanges”以正确的顺序插入它们

      【讨论】:

      • 这很好地回答了我原来的问题。我绝对需要复习我的实体框架。谢谢你的提示!
      猜你喜欢
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 1970-01-01
      • 2011-07-30
      相关资源
      最近更新 更多