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