'------------------------------------------------------------------------------ ' ' This code was generated from a template. ' ' Changes to this file may cause incorrect behavior and will be lost if ' the code is regenerated. ' '------------------------------------------------------------------------------ Imports System Imports System.Collections.Generic Imports System.Collections.ObjectModel Imports System.Collections.Specialized Imports System.ComponentModel Imports System.Globalization Imports System.Runtime.Serialization Imports System.Runtime.CompilerServices ' Helper class that captures most of the change tracking work that needs to be done ' for self tracking entities. Public Class ObjectChangeTracker #Region "Fields" Private _isDeserializing As Boolean Private _objectState As ObjectState = ObjectState.Added Private _originalValues As OriginalValuesDictionary Private _extendedProperties As ExtendedPropertiesDictionary Private _changeTrackingEnabled As Boolean Private _objectsAddedToCollections As New ObjectsAddedToCollectionProperties() Private _objectsRemovedFromCollections As New ObjectsRemovedFromCollectionProperties() #End Region #Region "Events" Public Event ObjectStateChanging As EventHandler(Of ObjectStateChangingEventArgs) #End Region Protected Overridable Sub OnObjectStateChanging(ByVal newState As ObjectState) RaiseEvent ObjectStateChanging(Me, New ObjectStateChangingEventArgs With {.NewState = newState}) End Sub Public Property State() As ObjectState Get Return _objectState End Get Set(ByVal value As ObjectState) If _isDeserializing Or _changeTrackingEnabled Then OnObjectStateChanging(value) _objectState = value End If End Set End Property Public Property ChangeTrackingEnabled() As Boolean Get Return _changeTrackingEnabled End Get Set(ByVal value As Boolean) _changeTrackingEnabled = value End Set End Property ' Returns the removed objects to collection valued properties that were changed. Public ReadOnly Property ObjectsRemovedFromCollectionProperties() As ObjectsRemovedFromCollectionProperties Get If _objectsRemovedFromCollections Is Nothing Then _objectsRemovedFromCollections = New ObjectsRemovedFromCollectionProperties() End If Return _objectsRemovedFromCollections End Get End Property ' Returns the original values for properties that were changed. Public ReadOnly Property OriginalValues() As OriginalValuesDictionary Get If _originalValues Is Nothing Then _originalValues = New OriginalValuesDictionary() End If Return _originalValues End Get End Property ' Returns the extended property values. ' This includes key values for independent associations that are needed for the ' concurrency model in the Entity Framework Public ReadOnly Property ExtendedProperties() As ExtendedPropertiesDictionary Get If _extendedProperties Is Nothing Then _extendedProperties = New ExtendedPropertiesDictionary() End If Return _extendedProperties End Get End Property ' Returns the added objects to collection valued properties that were changed. Public ReadOnly Property ObjectsAddedToCollectionProperties() As ObjectsAddedToCollectionProperties Get If _objectsAddedToCollections Is Nothing Then _objectsAddedToCollections = New ObjectsAddedToCollectionProperties() End If Return _objectsAddedToCollections End Get End Property #Region "MethodsForChangeTrackingOnClient" Public Sub OnDeserializingMethod(ByVal context As StreamingContext) _isDeserializing = True End Sub Public Sub OnDeserializedMethod(ByVal context As StreamingContext) _isDeserializing = False End Sub ' Resets the ObjectChangeTracker to the Unchanged state and ' clears the original values as well as the record of changes ' to collection properties Public Sub AcceptChanges() OnObjectStateChanging(ObjectState.Unchanged) OriginalValues.Clear() ObjectsAddedToCollectionProperties.Clear() ObjectsRemovedFromCollectionProperties.Clear() ChangeTrackingEnabled = True _objectState = ObjectState.Unchanged End Sub ' Captures the original value for a property that is changing. Friend Sub RecordOriginalValue(ByVal propertyName As String, ByVal value As Object) If _changeTrackingEnabled AndAlso _objectState <> ObjectState.Added Then If Not Me.OriginalValues.ContainsKey(propertyName) Then OriginalValues(propertyName) = value End If End If End Sub ' Records an addition to collection valued properties on SelfTracking Entities. Friend Sub RecordAdditionToCollectionProperties(ByVal propertyName As String, ByVal value As Object) If _changeTrackingEnabled Then ' Add the entity back after deleting it, we should do nothing here then If Me.ObjectsRemovedFromCollectionProperties.ContainsKey(propertyName) AndAlso Me.ObjectsRemovedFromCollectionProperties(propertyName).Contains(value) Then Me.ObjectsRemovedFromCollectionProperties(propertyName).Remove(value) If Me.ObjectsRemovedFromCollectionProperties(propertyName).Count = 0 Then Me.ObjectsRemovedFromCollectionProperties.Remove(propertyName) End If Exit Sub End If If Not Me.ObjectsAddedToCollectionProperties.ContainsKey(propertyName) Then ObjectsAddedToCollectionProperties(propertyName) = New ObjectList() ObjectsAddedToCollectionProperties(propertyName).Add(value) Else ObjectsAddedToCollectionProperties(propertyName).Add(value) End If End If End Sub ' Records a removal to collection valued properties on SelfTracking Entities. Friend Sub RecordRemovalFromCollectionProperties(ByVal propertyName As String, ByVal value As Object) If _changeTrackingEnabled Then ' Delete the entity back after adding it, we should do nothing here then If Me.ObjectsAddedToCollectionProperties.ContainsKey(propertyName) AndAlso Me.ObjectsAddedToCollectionProperties(propertyName).Contains(value) Then Me.ObjectsAddedToCollectionProperties(propertyName).Remove(value) If Me.ObjectsAddedToCollectionProperties(propertyName).Count = 0 Then Me.ObjectsAddedToCollectionProperties.Remove(propertyName) End If Exit Sub End If If Not Me.ObjectsRemovedFromCollectionProperties.ContainsKey(propertyName) Then ObjectsRemovedFromCollectionProperties(propertyName) = New ObjectList() ObjectsRemovedFromCollectionProperties(propertyName).Add(value) Else If Not ObjectsRemovedFromCollectionProperties(propertyName).Contains(value) Then ObjectsRemovedFromCollectionProperties(propertyName).Add(value) End If End If End If End Sub #End Region End Class #Region "EnumForObjectState" Public Enum ObjectState Unchanged = &H1 Added = &H2 Modified = &H4 Deleted = &H8 End Enum #End Region Public Class ObjectsAddedToCollectionProperties Inherits Dictionary(Of String, ObjectList) End Class Public Class ObjectsRemovedFromCollectionProperties Inherits Dictionary(Of String, ObjectList) End Class Public Class OriginalValuesDictionary Inherits Dictionary(Of String, Object) End Class Public Class ExtendedPropertiesDictionary Inherits Dictionary(Of String, Object) End Class Public Class ObjectList Inherits List(Of Object) End Class ' The interface is implemented by the self tracking entities that EF will generate. ' We will have an Adapter that converts this interface to the interface that the EF expects. ' The Adapter will live on the server side. Public Interface IObjectWithChangeTracker ' Has all the change tracking information for the subgraph of a given object. Property ChangeTracker() As ObjectChangeTracker End Interface Public Class ObjectStateChangingEventArgs Inherits EventArgs Private _NewState As ObjectState Public Property NewState() As ObjectState Get Return _NewState End Get Set(ByVal value As ObjectState) _NewState = value End Set End Property End Class Public Module ObjectWithChangeTrackerExtensions Public Function MarkAsDeleted(Of T As IObjectWithChangeTracker)(ByVal trackingItem As T) As T If trackingItem Is Nothing Then Throw New ArgumentNullException("trackingItem") End If trackingItem.ChangeTracker.ChangeTrackingEnabled = True trackingItem.ChangeTracker.State = ObjectState.Deleted Return trackingItem End Function Public Function MarkAsAdded(Of T As IObjectWithChangeTracker)(ByVal trackingItem As T) As T If trackingItem Is Nothing Then Throw New ArgumentNullException("trackingItem") End If trackingItem.ChangeTracker.ChangeTrackingEnabled = True trackingItem.ChangeTracker.State = ObjectState.Added Return trackingItem End Function Public Function MarkAsModified(Of T As IObjectWithChangeTracker)(ByVal trackingItem As T) As T If trackingItem Is Nothing Then Throw New ArgumentNullException("trackingItem") End If trackingItem.ChangeTracker.ChangeTrackingEnabled = True trackingItem.ChangeTracker.State = ObjectState.Modified Return trackingItem End Function Public Function MarkAsUnchanged(Of T As IObjectWithChangeTracker)(ByVal trackingItem As T) As T If trackingItem Is Nothing Then Throw New ArgumentNullException("trackingItem") End If trackingItem.ChangeTracker.ChangeTrackingEnabled = True trackingItem.ChangeTracker.State = ObjectState.Unchanged Return trackingItem End Function Public Sub StartTracking(ByVal trackingItem As IObjectWithChangeTracker) If trackingItem Is Nothing Then Throw New ArgumentNullException("trackingItem") End If trackingItem.ChangeTracker.ChangeTrackingEnabled = True End Sub Public Sub StopTracking(ByVal trackingItem As IObjectWithChangeTracker) If trackingItem Is Nothing Then Throw New ArgumentNullException("trackingItem") End If trackingItem.ChangeTracker.ChangeTrackingEnabled = False End Sub Public Sub AcceptChanges(ByVal trackingItem As IObjectWithChangeTracker) If trackingItem Is Nothing Then Throw New ArgumentNullException("trackingItem") End If trackingItem.ChangeTracker.AcceptChanges() End Sub End Module ' An System.Collections.ObjectModel.ObservableCollection that raises ' individual item removal notifications on clear and prevents adding duplicates. Public Class TrackableCollection(Of T) Inherits ObservableCollection(Of T) Protected Overrides Sub ClearItems() Dim items As New List(Of T)(Me) items.ForEach(Function(t) Remove(t)) End Sub Protected Overloads Overrides Sub InsertItem(ByVal index As Integer, ByVal item As T) If Not Me.Contains(item) Then MyBase.InsertItem(index, item) End If End Sub End Class ' An interface that provides an event that fires when complex properties change. ' Changes can be the replacement of a complex property with a new complex type instance or ' a change to a scalar property within a complex type instance. Public Interface INotifyComplexPropertyChanging Event ComplexPropertyChanging As EventHandler End Interface Public Module EqualityComparer ' Helper method to determine if two byte arrays are the same value even if they are different object references Public Function BinaryEquals(ByVal binaryValue1 As Object, ByVal binaryValue2 As Object) As Boolean If Object.ReferenceEquals(binaryValue1, binaryValue2) Then Return True End If Dim array1 As Byte() = TryCast(binaryValue1, Byte()) Dim array2 As Byte() = TryCast(binaryValue2, Byte()) If array1 IsNot Nothing AndAlso array2 IsNot Nothing Then If array1.Length <> array2.Length Then Return False End If For i As Integer = 0 To array1.Length - 1 If array1(i) <> array2(i) Then Return False End If Next Return True End If Return False End Function End Module