Reputation: 1669
I'm migrating a large project from ObjectContext to DbContext, EF6.1.3. Just run into an issue which will be hard to track down instances of reliably in the source code, and am wondering if there may be an approach whereby I can simulate the ObjectContext behaviour.
Consider two classes, Parent and Child. Parent has zero or more Child objects. At the table level, Child has a ParentID column which is in an FK relationship with the ID column in the Parent object. Here are the two POCO classes I generated to illustrate the issue:
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
and here is a small program to illustrate the issue:
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
With an ObjectContext implementation, Adding the Child to the Parent will also set the Child's Parent property. With DbContext this doesn't happen until the session is commited.
In the code I am migrating there are several places (that we've found so far) where code will be passed the equivalent of a Child object that has been added to a Parent, then attempt to reference the Parent object through the Child's Parent property. These compile correctly, but the runtime behaviour is "broken" with DbContext. Finding all such instances where this pattern is used will be costly and it will be very easy to miss cases that will then go on to cause problems at runtime. Can anyone suggest a workaround that will allow the code to work as is? I suppose we could modify the TT file to generate our own class instead of a HashSet for the Children property, implement a constructor that takes a reference to the dependant property, and an Add method that updates the dependent property. Before we go down that route, though, is there anything simpler that we may have missed?
Upvotes: 0
Views: 232
Reputation: 4346
I'm not entirely sure this would work, but I think it is worth a try. First, after you add the parent and children, try calling this on the DbContext:
ChangeTracker.DetectChanges()
If this results in what you want, you might be able to create your own DbSet that will call this automatically whenever Add is called... Even if you have to Shadow the Add method. (Hopefully there is just an event you can handle.)
Upvotes: 1