【问题标题】:Entity Framework 5 won't insert self referencing many to many relationshipEntity Framework 5 不会插入自引用多对多关系
【发布时间】:2013-01-02 17:17:53
【问题描述】:

我不明白为什么这个配置不会向数据库生成插入语句。我正在通过 SQL Profiler 进行检查。

这是我通过 Visio 制作的模型:

这是我的 edmx(首先是数据库)。圆圈显示返回到 GeoBoundary 的自引用关系。

这是我的代码:

public void UpdateAssocs(Dictionary<int, List<int>> fromTo) {
  //iterate through each dictionary entry
  foreach (KeyValuePair<int, List<int>> entry in fromTo) {
    using (TransactionScope scope = new TransactionScope()) {
      //get a reference to the parent geoboundary for this entry
      GeoBoundary parent = contactContext.GeoBoundaries
        .FirstOrDefault(x => x.GeoID == entry.Key);
      //test to see if the parent is null, it shouldn't be b/c this dictionary was generated 
      // from a list of database values (but shit happens so throw an error if it is null)
      if (parent != null) {
        foreach (int childID in entry.Value) {
          //check to see if the child exists in the parents list of children
          GeoBoundary child = parent.GeoBoundaryAssocTo
            .FirstOrDefault(x => x.GeoID == childID);
          if (child == null) {
            //get a ref to the GeoBoundary that SHOULD be tied to the parent (it should exist but there just 
            // isn't an established relationship in the db)
            child = contactContext.GeoBoundaries
              .FirstOrDefault(x => x.GeoID == childID);
            //check the damn thing again b/c you never want to assume...
            // but if it's still null then do nothing!
            if (child != null) {
              parent.GeoBoundaryAssocTo.Add(child);                  
              contactContext.SaveChanges();
            }
          }
        }
      }
      else {
        throw new Exception(@"Parent GeoID passed to UpdateAssocs method or GeoID is null.");
      }
      scope.Complete();
    }
  }
}

当我在调试器中到达parent.GeoBoundaryAssocTo.Add(child); 时,我确保父母和孩子都存在,然后我单步执行,但我在分析器中什么也没有。是什么赋予了?两个实体都已经存在于数据库中并且除了关系之外我没有改变任何东西,这是一个问题吗?如果是这样,那么我如何将关系标记为已更改,以便 EF 生成插入?

EDMX 详细信息:

    <AssociationSet Name="GeoBoundaryAssociation" Association="Contact.GeoBoundaryAssociation">
      <End Role="GeoBoundary" EntitySet="GeoBoundaries" />
      <End Role="GeoBoundary1" EntitySet="GeoBoundaries" />
    </AssociationSet>

    <Association Name="GeoBoundaryAssociation">
      <End Type="Contact.GeoBoundary" Role="GeoBoundary" Multiplicity="*" />
      <End Type="Contact.GeoBoundary" Role="GeoBoundary1" Multiplicity="*" />
    </Association>

【问题讨论】:

  • 为什么是 TransactionScope?
  • @ScottStafford - 如果Dictionary&lt;int, List&lt;int&gt;&gt; 中的某些内容不正确,我希望整个事情都失败。
  • 当然 - 但如果您不在 contactContext 上 SaveChanges() 并且只是将 contactContext 扔掉,它无论如何都会这样做。上下文是一个工作单元——当您希望能够在 SaveChanges() 或类似的事情之后回滚时,您只需要 TransactionScope...
  • 你能粘贴相关的 .edmx XML,就像回答者粘贴在这里:stackoverflow.com/a/9760255/237091
  • .edmx XML 已发布,如果部分不正确,请告诉我。

标签: c# entity-framework entity-framework-5 self-reference


【解决方案1】:

您需要确保您的导航属性附加到当前 DBContext。否则 EF 将忽略它。

试试这个:

...

//get a reference to the parent geoboundary for this entry
GeoBoundary parent = contactContext.GeoBoundaries
    .include("GeoBoundaryAssocTo")
    .FirstOrDefault(x => x.GeoID == entry.Key);

...
// You may need to use include on your child entity too.

【讨论】:

  • 您是否也尝试拉入子项的导航属性?
  • 像这样在两者上包括多对多的两端怎么样: GeoBoundary parent = contactContext.GeoBoundaries .include("GeoBoundaryAssocTo").include("GeoBoundaryAssocFrom") .FirstOrDefault(x => x .GeoID == entry.Key);
  • 我也试过了。我找到了其他人成功完成这项工作的博客,所以我不会失去希望。
  • 有趣的是,在调试器中,当parent.GeoBoundaryAssocTo.Add(child); 执行时,我可以看到 GeoBoundaryAssocTo 集合计数器在哪里加一。就像 EF 只是没有意识到它已经改变了。
【解决方案2】:

好吧,我是我自己不幸的根源。我没有意识到我正在重用我的contactContext(实例化为服务类),并且在之前的方法方法调用中我设置了AutoDetectChangesEnabled = false;。我需要做的就是重新打开更改跟踪。不知何故,我从来没有想过服务类在以前的调用中保持了它的状态。生活和学习。

【讨论】:

    猜你喜欢
    • 2017-02-27
    • 2011-06-26
    • 2018-06-24
    • 2021-04-09
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    相关资源
    最近更新 更多