0

I'm using Entity Framework 6 , with Database First. The model is created using wizard from existing Sql server database. I'm using this code to do a deep clone :

Imports System.ComponentModel
Imports System.Collections
Imports System.Data.Entity.Core.Objects.DataClasses
Imports System.Runtime.Serialization
Imports System.IO
Imports System.Reflection
Imports System.Runtime.CompilerServices

Module Extensions

Private Function ClearEntityObject(Of T As Class)(ByVal source As T, ByVal bCheckHierarchy As Boolean) As T
    If (source Is Nothing) Then
        Throw New Exception("Null Object cannot be cloned")
    End If
    Dim tObj As Type = source.GetType
    If (Not tObj.GetProperty("EntityKey") Is Nothing) Then
        tObj.GetProperty("EntityKey").SetValue(source, Nothing, Nothing)
    End If
    If bCheckHierarchy Then
        Dim PropertyList As List(Of PropertyInfo) = Enumerable.ToList(Of PropertyInfo)((From a In source.GetType.GetProperties
            Where a.PropertyType.Name.Equals("ENTITYCOLLECTION`1", StringComparison.OrdinalIgnoreCase)
            Select a))
        Dim prop As PropertyInfo
        For Each prop In PropertyList
            Dim keys As IEnumerable = DirectCast(tObj.GetProperty(prop.Name).GetValue(source, Nothing), IEnumerable)
            Dim key As Object
            For Each key In keys
                Dim childProp As EntityReference = Enumerable.SingleOrDefault(Of PropertyInfo)((From a In key.GetType.GetProperties
                Where (a.PropertyType.Name.Equals("EntityReference`1", StringComparison.OrdinalIgnoreCase))
                    Select a)).GetValue(key, Nothing)

                ClearEntityObject(childProp, False)
                ClearEntityObject(key, True)
            Next
        Next
    End If
    Return source
End Function

<Extension()> _
Public Function ClearEntityReference(ByVal source As Object, ByVal bCheckHierarchy As Boolean) As Object
    Return ClearEntityObject(source, bCheckHierarchy)
End Function

<Extension()> _
Public Function Clone(Of T)(ByVal source As T) As T
    Dim ser As New DataContractSerializer(GetType(T))
    Using stream As MemoryStream = New MemoryStream
        ser.WriteObject(stream, source)
        stream.Seek(0, SeekOrigin.Begin)
        Return DirectCast(ser.ReadObject(stream), T)
    End Using
End Function

End module

Now , I try to use this code like this :

  Private Sub DoClone
    Dim litm, newitm As MyObject
    litm = context.MyObjects.FirstOrDefault
    newitm = litm.Clone()
    newitm.ClearEntityReference(True)
    context.MyObjects.Add(newitm)
    context.SaveChanges()
End Sub

I get an error :

An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in System.Runtime.Serialization.dll

Additional information:Type 'System.Data.Entity.DynamicProxies.MyObject_F2FFE64DA472EB2B2BDF7E143DE887D3845AD9D1731FD3107937062AC0C2E4BB' with data contract name 'MyObject_F2FFE64DA472EB2B2BDF7E143DE887D3845AD9D1731FD3107937062AC0C2E4BB:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected.

Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

This is my model that I use :

Partial Public Class Myobject
Public Property id As Integer
Public property name as string
Public Overridable Property chld As ICollection(Of chld) = New HashSet(Of chld) 
Public Overridable Property chld1 As ICollection(Of chld1) = New HashSet(Of chld1)
End Class

Partial Public Class chld
    Public Property id As Integer
    Public Property date1 as DateTime
    Public Property quantity as Integer
    Public Property ParentID as integer
    Public Overridable Property MyObj1 As MyObject
End Class

Partial Public Class chld1
    Public Property id As Integer
    Public Property nm as string
    Public Property ParentID as integer
    Public Overridable Property MyObj1 As MyObject
End Class 
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
alex
  • 694
  • 3
  • 15
  • 35
  • Have you considered using a `DataContractResolver` or adding any types not known statically to the list of known types - for example, by using the `KnownTypeAttribute` attribute or by adding them to the list of known types passed to `DataContractSerializer`? – Robert Harvey Apr 11 '15 at 19:22
  • I don't know how to do this.Can you give me a little help ? – alex Apr 11 '15 at 19:23
  • That's what your error message is telling you to do. In a generalized Deep Clone method, that's probably not practical. Have you seen this? http://stackoverflow.com/questions/78536/deep-cloning-objects – Robert Harvey Apr 11 '15 at 19:25
  • Sorry friend , but in the link there are several solution. Which of them should I read ? – alex Apr 11 '15 at 19:27
  • I get an error that the type is not marked as serializable. So I should add the [seriazable] to all of my class in the model ?. – alex Apr 11 '15 at 19:40
  • That would appear to be the case, since the accepted answer uses binary serialization to perform the deep copy. – Robert Harvey Apr 11 '15 at 19:45
  • I get error , because when I add the serializable tag , the type is not loaded. – alex Apr 11 '15 at 19:52

0 Answers0