【问题标题】:DbContext vs ObjectContext - navigation property behaviour changeDbContext vs ObjectContext - 导航属性行为改变
【发布时间】:2017-04-12 16:54:39
【问题描述】:

我正在将一个大型项目从 ObjectContext 迁移到 DbContext,EF6.1.3。只是遇到了一个很难在源代码中可靠地跟踪实例的问题,并且想知道是否有一种方法可以模拟 ObjectContext 行为。

考虑两个类,Parent 和 Child。 Parent 有零个或多个 Child 对象。在表级别,Child 有一个 ParentID 列,该列与 Parent 对象中的 ID 列处于 FK 关系。以下是我为说明问题而生成的两个 POCO 类:

Partial Public Class Parent
    Public Property ID As Integer

    Public Overridable Property Children As ICollection(Of Child) = New HashSet(Of Child)

End Class

Partial Public Class Child
    Public Property ID As Integer
    Public Property ParentID As Integer

    Public Overridable Property Parent As Parent

End Class

这里有一个小程序来说明这个问题:

  Sub Main()
    Using session As New testEntities
      Dim parent = session.Parents.Add(session.Parents.Create)
      Dim child = session.Children.Create
      parent.Children.Add(child)
      Console.WriteLine(child.Parent Is Nothing)
      session.SaveChanges()
      Console.WriteLine(child.Parent Is Nothing)
    End Using

使用 ObjectContext 实现,将 Child 添加到 Parent 也会设置 Child 的 Parent 属性。使用 DbContext 直到提交会话才会发生这种情况。

在我要迁移的代码中,有几个地方(到目前为止我们已经找到),其中代码将被传递给已添加到 Parent 的 Child 对象的等价物,然后尝试通过孩子的父母财产。这些编译正确,但运行时行为被 DbContext “破坏”。 查找使用此模式的所有此类实例将是昂贵的,并且很容易错过随后会在运行时导致问题的案例。任何人都可以提出一个允许代码按原样工作的解决方法吗?我想我们可以修改 TT 文件以生成我们自己的类,而不是为 Children 属性生成一个 HashSet,实现一个获取依赖属性引用的构造函数,以及一个更新依赖属性的 Add 方法。不过,在我们走这条路之前,有没有什么更简单的事情我们可能错过了?

【问题讨论】:

  • 我认为这与ObjectContextDbContext 无关,而是实体类(POCO 与特殊)。你是说你使用了与ObjectContext 完全相同的实体类?
  • 这在一定程度上是正确的——使用 ObjectContext,导航属性由 EntityCollection 类型支持——但使用 DbContext,实体本身被代理包装,这将提供另一个机会来做类似的事情
  • 哦,不,这两种情况下的类并不相同,但它们都是由关联的 TT 文件生成的
  • 所以基本上区别来自旧场景中使用的特殊 EntityCollection 类与第二个中使用的普通 CLR 集合类型。虽然代理可以拦截虚拟属性访问,但它不能拦截集合Add / Remove 等。所以DbContext 导航属性修复发生在某些上下文操作上 - SaveChangesDbSet.Add 等。问题是代码首先将父级添加到数据库集,然后添加子级。您可能需要走您提到的路线。
  • 是的,这就是我所做的。它似乎工作正常。从长远来看,我需要想出一种方法来发现所有使用这种模式的代码,并替换它

标签: entity-framework-6 dbcontext objectcontext


【解决方案1】:

我不完全确定这会奏效,但我认为值得一试。首先,在添加了父级和子级之后,尝试在 DbContext 上调用它:

ChangeTracker.DetectChanges()

如果这会产生您想要的结果,您也许可以创建自己的 DbSet,它会在调用 Add 时自动调用它...即使您必须隐藏 Add 方法。 (希望只有您可以处理的事件。)

【讨论】:

  • DetectChanges 确实有效。不过,我还没有尝试将它集成到解决方案中,因为我已经编写了一种将 HashSet 子类化的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 2012-04-10
  • 1970-01-01
相关资源
最近更新 更多