' Feel free not to use a Tuple here... this was just a
' quick way to demonstrate the code
<Extension()> _
Public Function GetTrackedObjects(Of T)(ByVal dc As DataContext) As IList(Of Tuple(Of T, T))
	Dim result As New List(Of Tuple(Of T, T))
	Dim dcType = GetType(DataContext)

	' Use reflection to get to the underlying items being tracked in the DataContext
	Dim bindings = BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.GetField
	Dim services = dcType.GetField("services", bindings).GetValue(dc)
	Dim tracker = services.GetType().GetField("tracker", bindings).GetValue(services)
	Dim trackerItems = DirectCast(tracker.GetType().GetField("items", bindings).GetValue(tracker), IDictionary)

	' iterate through each update in context, adding only those that are of type T to the method's result variable
	For Each entry As DictionaryEntry In trackerItems
		Dim original As Object = entry.Value.GetType().GetField("original", bindings).GetValue(entry.Value)
		If TypeOf entry.Key Is T AndAlso TypeOf original Is T Then
			result.Add(New Tuple(Of T, T)(DirectCast(original, T), DirectCast(entry.Key, T)))
		End If

	Return result
End Function
Option Infer On

Dim dc As New DataContext()
' get linq-to-sql objects from a DataContext

' Examine the DataContext for objects tracked
Dim changeHistoryList = dc.GetTrackedObjects(Of People)()
For Each potentialChange In changeHistoryList
   Dim original = potentialChange.Item1
   Dim current = potentialChange.Item2
   If original.Salary <> current.Salary Then
      Console.WriteLine("Salary changed from {0} to {1} for {2}", original.Salary, current.Salary, original.ID)
   End If


A Linq-to-SQL DataContext does change tracking for all the objects it creates. This is so that it knows what to insert/update when you call .SubmitChanges(). Unfortunately, the DataContext doesn't supply that information to the world, but it's uber helpful to know at times, especially if you want to create a DAL that enforces writing to a changelog on every DB commit. This method examines the gruesome innards of the DataContext and gives you the


Double click on the code to select all.