why this code doesn't work ?
-
Hello ! This is a code that is supposed to do a copy of an entity framework object with the childs collection that the user want.
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Imports System.Runtime.CompilerServicesPublic Module Entities
Public Function CloneEntity(Of T As Class)(entity As T, context As ObjectContext, Optional include As List(Of IncludeEntity) = Nothing, Optional copyKeys As Boolean = False) As T
Return CloneEntityHelper(entity, context, include, copyKeys)
End FunctionPrivate Function CloneEntityHelper(Of T As Class)(entity As T, context As ObjectContext, Optional include As List(Of IncludeEntity) = Nothing, Optional copyKeys As Boolean = False) As T
If include Is Nothing Then include = New List(Of IncludeEntity)()
Dim myType = entity.GetType()
Dim methodInfo = context.GetType().GetMethod("CreateObject").MakeGenericMethod(myType)
Dim result = methodInfo.Invoke(context, Nothing)
Dim propertyInfo = entity.GetType().GetProperties()
For Each info In propertyInfo
Dim attributes = info.GetCustomAttributes(GetType(EdmScalarPropertyAttribute), False).ToList()For Each attr As EdmScalarPropertyAttribute In attributes If (Not copyKeys) AndAlso attr.EntityKeyProperty Continue For End If info.SetValue(result, info.GetValue(entity, Nothing), Nothing) Next If info.PropertyType.Name.Equals("EntityCollection\`1", StringComparison.OrdinalIgnoreCase) Then Dim shouldInclude = include.SingleOrDefault(Function(i) i.Name.Equals(info.Name, StringComparison.OrdinalIgnoreCase)) If shouldInclude Is Nothing Then Continue For Dim relatedChildren = info.GetValue(entity, Nothing) Dim propertyType As Type = relatedChildren.GetType().GetGenericArguments().First() Dim genericType As Type = GetType(EntityCollection(Of )) Dim boundType = genericType.MakeGenericType(propertyType) Dim children = Activator.CreateInstance(boundType) For Each child In relatedChildren Dim cloneChild = CloneEntityHelper(child, context, shouldInclude.Children, shouldInclude.CopyKeys) children.Add(cloneChild) Next info.SetValue(result, children, Nothing) End If Next Return result End Function
Public Class IncludeEntity
Public Property Name As String
Public Property Children As New List(Of IncludeEntity)
Public Property CopyKeys As Boolean -
Hello ! This is a code that is supposed to do a copy of an entity framework object with the childs collection that the user want.
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Imports System.Runtime.CompilerServicesPublic Module Entities
Public Function CloneEntity(Of T As Class)(entity As T, context As ObjectContext, Optional include As List(Of IncludeEntity) = Nothing, Optional copyKeys As Boolean = False) As T
Return CloneEntityHelper(entity, context, include, copyKeys)
End FunctionPrivate Function CloneEntityHelper(Of T As Class)(entity As T, context As ObjectContext, Optional include As List(Of IncludeEntity) = Nothing, Optional copyKeys As Boolean = False) As T
If include Is Nothing Then include = New List(Of IncludeEntity)()
Dim myType = entity.GetType()
Dim methodInfo = context.GetType().GetMethod("CreateObject").MakeGenericMethod(myType)
Dim result = methodInfo.Invoke(context, Nothing)
Dim propertyInfo = entity.GetType().GetProperties()
For Each info In propertyInfo
Dim attributes = info.GetCustomAttributes(GetType(EdmScalarPropertyAttribute), False).ToList()For Each attr As EdmScalarPropertyAttribute In attributes If (Not copyKeys) AndAlso attr.EntityKeyProperty Continue For End If info.SetValue(result, info.GetValue(entity, Nothing), Nothing) Next If info.PropertyType.Name.Equals("EntityCollection\`1", StringComparison.OrdinalIgnoreCase) Then Dim shouldInclude = include.SingleOrDefault(Function(i) i.Name.Equals(info.Name, StringComparison.OrdinalIgnoreCase)) If shouldInclude Is Nothing Then Continue For Dim relatedChildren = info.GetValue(entity, Nothing) Dim propertyType As Type = relatedChildren.GetType().GetGenericArguments().First() Dim genericType As Type = GetType(EntityCollection(Of )) Dim boundType = genericType.MakeGenericType(propertyType) Dim children = Activator.CreateInstance(boundType) For Each child In relatedChildren Dim cloneChild = CloneEntityHelper(child, context, shouldInclude.Children, shouldInclude.CopyKeys) children.Add(cloneChild) Next info.SetValue(result, children, Nothing) End If Next Return result End Function
Public Class IncludeEntity
Public Property Name As String
Public Property Children As New List(Of IncludeEntity)
Public Property CopyKeys As BooleanPlease include your class-definition of MyObject (you can omit the methods, if it has any). Did you already observe it in debug-mode?
-
Please include your class-definition of MyObject (you can omit the methods, if it has any). Did you already observe it in debug-mode?
Thank you ! I put some breakpoints , and I have detected that maybe the problem may be this line : Dim attributes = info.GetCustomAttributes(GetType(EdmScalarPropertyAttribute), False).ToList() . The attributes always have the Length=0 , so all the codes inside the For Each info In propertyInfo doesn;t get executed , and goes to next for each info and so at the end the result is an empty object. What can I do ? also I did another test ( maybe a stupid test but anyway ) : I put the line info.SetValue(result, info.GetValue(entity, Nothing), Nothing) after the next so outside the for loop. Now the entity is copied , but not the child that is included on inc variable. ? The code is supposed to work will any kind of classes , but anyway this are the classes where I made the tests:
Partial Public Class Myobject
Public Property id As Integer
Public property name as string
Public Overridable Property Child_list As ICollection(Of Child_list) = New HashSet(Of Child_list)
End ClassPartial Public Class Child_list
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 -
Thank you ! I put some breakpoints , and I have detected that maybe the problem may be this line : Dim attributes = info.GetCustomAttributes(GetType(EdmScalarPropertyAttribute), False).ToList() . The attributes always have the Length=0 , so all the codes inside the For Each info In propertyInfo doesn;t get executed , and goes to next for each info and so at the end the result is an empty object. What can I do ? also I did another test ( maybe a stupid test but anyway ) : I put the line info.SetValue(result, info.GetValue(entity, Nothing), Nothing) after the next so outside the for loop. Now the entity is copied , but not the child that is included on inc variable. ? The code is supposed to work will any kind of classes , but anyway this are the classes where I made the tests:
Partial Public Class Myobject
Public Property id As Integer
Public property name as string
Public Overridable Property Child_list As ICollection(Of Child_list) = New HashSet(Of Child_list)
End ClassPartial Public Class Child_list
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 ClassCorrect, the code you have there is expecting an EdmScalarPropertyAttribute on each field or property that should be copied (with the exception of _EntityCollection_s). You didn't decorate the properties of your class with this attribute, so the SetValue(..)-line was skipped. Note: I'm not familiar with EF. My following advice should make your CloneEntity-code work (or at least "almost working") but someone who knows about EF might have more to say about it. In particular, I have no idea where the id of your classes gets initialized; if you have to deal with that yourself or if it's somehow magically done for you. - Move the SetValue(..)-line back to where it was. - Put an EdmScalarPropertyAttribute on the name-property of the Myobject-class and on all properties of the Child_list-class (except id and ParentID) like so:
Public property name as string
- In CloneEntityHelper(..), change the string "EntityCollection`1" to "ICollection`1". - If you want to have children of children copied (to an arbitrary depth), set the Children-property of your IncludeEntity-instance to the same IncludeEntity-instance. - If you have to initialize id yourself, you will have to set it for _Myobject_s, _Child_list_s and potentially further nested objects, after the call to CloneEntity(..). - Because of the self-referencing through ParentID you will have to set ParentID for all children (and potentially children of children) to their respective parent's id after the call to CloneEntity(..) (in any case). That should be it I think..
-
Thank you ! I put some breakpoints , and I have detected that maybe the problem may be this line : Dim attributes = info.GetCustomAttributes(GetType(EdmScalarPropertyAttribute), False).ToList() . The attributes always have the Length=0 , so all the codes inside the For Each info In propertyInfo doesn;t get executed , and goes to next for each info and so at the end the result is an empty object. What can I do ? also I did another test ( maybe a stupid test but anyway ) : I put the line info.SetValue(result, info.GetValue(entity, Nothing), Nothing) after the next so outside the for loop. Now the entity is copied , but not the child that is included on inc variable. ? The code is supposed to work will any kind of classes , but anyway this are the classes where I made the tests:
Partial Public Class Myobject
Public Property id As Integer
Public property name as string
Public Overridable Property Child_list As ICollection(Of Child_list) = New HashSet(Of Child_list)
End ClassPartial Public Class Child_list
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 ClassDid you get it to work?