Kevin O'Donovan
Kevin O'Donovan

Reputation: 1669

DbContext vs ObjectContext - navigation property behaviour change

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

Answers (1)

Daniel Lorenz
Daniel Lorenz

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

Related Questions