Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. Entity Framework : Clone an object and only its childs

Entity Framework : Clone an object and only its childs

Scheduled Pinned Locked Moved Visual Basic
jsontutorialcsharpcomhelp
12 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    dilkonika
    wrote on last edited by
    #1

    Hello ! I have see several methods around for deep cloning an entity framework object. All these methods use serialization. But sometimes these methods are not creating what I want. For example I try to use the Json.net (http://www.newtonsoft.com/json[^]) to serialize and after to deserialize a object. And after I use this code to clone :

    <Extension> _
    Public Function CloneJson(Of T)(source As T) As T
    If [Object].ReferenceEquals(source, Nothing) Then
    Return Nothing
    End If
    Return JsonConvert.DeserializeObject(Of T)(JsonConvert.SerializeObject(source))
    End Function

    But look how an object is cloned on my case : ( I want to clone a student and its Results )

    Student ID......... Name........Age
    1...........George........21

    Course_ID..........Description Type
    1.....................Math........1

    Result_ID..........Course_ID......Student_ID..... Point
    1......................1...............1..........30

    And after the cloning :

    Student ID......... Name........Age
    1...........George........21
    2...........George........21

    Course_ID..........Description Type
    1.....................Math...........1
    2.....................Math...........1

    Result_ID..........Course_ID......Student_ID..... Point
    1......................1...............1..........30
    2......................2...............2..........30

    So now are 2 courses with name "Math". but I don't want to clone the courses. How to resolve this problem ? Thank you !

    S 1 Reply Last reply
    0
    • D dilkonika

      Hello ! I have see several methods around for deep cloning an entity framework object. All these methods use serialization. But sometimes these methods are not creating what I want. For example I try to use the Json.net (http://www.newtonsoft.com/json[^]) to serialize and after to deserialize a object. And after I use this code to clone :

      <Extension> _
      Public Function CloneJson(Of T)(source As T) As T
      If [Object].ReferenceEquals(source, Nothing) Then
      Return Nothing
      End If
      Return JsonConvert.DeserializeObject(Of T)(JsonConvert.SerializeObject(source))
      End Function

      But look how an object is cloned on my case : ( I want to clone a student and its Results )

      Student ID......... Name........Age
      1...........George........21

      Course_ID..........Description Type
      1.....................Math........1

      Result_ID..........Course_ID......Student_ID..... Point
      1......................1...............1..........30

      And after the cloning :

      Student ID......... Name........Age
      1...........George........21
      2...........George........21

      Course_ID..........Description Type
      1.....................Math...........1
      2.....................Math...........1

      Result_ID..........Course_ID......Student_ID..... Point
      1......................1...............1..........30
      2......................2...............2..........30

      So now are 2 courses with name "Math". but I don't want to clone the courses. How to resolve this problem ? Thank you !

      S Offline
      S Offline
      Sascha Lefevre
      wrote on last edited by
      #2

      You could put a JsonIgnoreAttribute on the property of the student-class that references the course(s). Which would, as the name implies, exclude it from the serialization and thereby from the cloning. http://www.newtonsoft.com/json/help/html/SerializationAttributes.htm[^] But if you would want to serialize student-objects elsewhere including their courses, that method would obviously not be suitable. In that case you would have to choose a different approach; please refer to: C# Object Clone Wars[^] http://stackoverflow.com/questions/21116554/proper-way-to-implement-icloneable[^] https://msdn.microsoft.com/en-us/library/system.icloneable%28v=vs.110%29.aspx[^] (Might be interesting reads in any case.)

      D 2 Replies Last reply
      0
      • S Sascha Lefevre

        You could put a JsonIgnoreAttribute on the property of the student-class that references the course(s). Which would, as the name implies, exclude it from the serialization and thereby from the cloning. http://www.newtonsoft.com/json/help/html/SerializationAttributes.htm[^] But if you would want to serialize student-objects elsewhere including their courses, that method would obviously not be suitable. In that case you would have to choose a different approach; please refer to: C# Object Clone Wars[^] http://stackoverflow.com/questions/21116554/proper-way-to-implement-icloneable[^] https://msdn.microsoft.com/en-us/library/system.icloneable%28v=vs.110%29.aspx[^] (Might be interesting reads in any case.)

        D Offline
        D Offline
        dilkonika
        wrote on last edited by
        #3

        sorry , maybe you have misunderstand. The Student class has not reference to Courses. Results class has reference to courses. So as you can see I want to clone the student and its results. But each result has a reference to courses. so the deep cloning methods are duplicating the courses too.

        S 1 Reply Last reply
        0
        • S Sascha Lefevre

          You could put a JsonIgnoreAttribute on the property of the student-class that references the course(s). Which would, as the name implies, exclude it from the serialization and thereby from the cloning. http://www.newtonsoft.com/json/help/html/SerializationAttributes.htm[^] But if you would want to serialize student-objects elsewhere including their courses, that method would obviously not be suitable. In that case you would have to choose a different approach; please refer to: C# Object Clone Wars[^] http://stackoverflow.com/questions/21116554/proper-way-to-implement-icloneable[^] https://msdn.microsoft.com/en-us/library/system.icloneable%28v=vs.110%29.aspx[^] (Might be interesting reads in any case.)

          D Offline
          D Offline
          dilkonika
          wrote on last edited by
          #4

          and sorry , but I;m thinking is there any way to have a function that take as argument an object and the child that I want to copy. and just to loop through all the property list of the object and to copy the values to a new object. The same thing with the child. Of course I'm speaking to create a general function that will work on all similar case ( not with a specific object ). Is there any suggestions how I can do that ? Thank you !

          S 1 Reply Last reply
          0
          • D dilkonika

            sorry , maybe you have misunderstand. The Student class has not reference to Courses. Results class has reference to courses. So as you can see I want to clone the student and its results. But each result has a reference to courses. so the deep cloning methods are duplicating the courses too.

            S Offline
            S Offline
            Sascha Lefevre
            wrote on last edited by
            #5

            Alright - but that doesn't completely invalidate my answer: - If you nowhere else need to serialize results (at least not with Json.Net) then you could use the JsonIgnoreAttribute on the reference to the courses in the results-class. - Else you would have to implement custom methods for cloning in the student- and results-classes for which you find pointers in the links I have provided you.

            1 Reply Last reply
            0
            • D dilkonika

              and sorry , but I;m thinking is there any way to have a function that take as argument an object and the child that I want to copy. and just to loop through all the property list of the object and to copy the values to a new object. The same thing with the child. Of course I'm speaking to create a general function that will work on all similar case ( not with a specific object ). Is there any suggestions how I can do that ? Thank you !

              S Offline
              S Offline
              Sascha Lefevre
              wrote on last edited by
              #6

              As you have seen in the other thread, I've had a small discussion with Eddy Vluggen if his downvote on one of your replies was justified because I initially doubted it. Now I'm starting to realize what he meant by "it's a recurring theme" - because it looks like you don't thoroughly read our replies or don't evaluate provided links before asking again. You would have found the answer to your question above if you had taken a look at my link "C# Object Clone Wars", namely the section "Clone with Reflection" which includes a link to a sample. You should work on that if you want to keep getting responses to your questions. We've answered them so far because we enjoy helping but if you don't value our answers by putting some effort into comprehending them and following provided links, it becomes a bit tiresome.

              D 1 Reply Last reply
              0
              • S Sascha Lefevre

                As you have seen in the other thread, I've had a small discussion with Eddy Vluggen if his downvote on one of your replies was justified because I initially doubted it. Now I'm starting to realize what he meant by "it's a recurring theme" - because it looks like you don't thoroughly read our replies or don't evaluate provided links before asking again. You would have found the answer to your question above if you had taken a look at my link "C# Object Clone Wars", namely the section "Clone with Reflection" which includes a link to a sample. You should work on that if you want to keep getting responses to your questions. We've answered them so far because we enjoy helping but if you don't value our answers by putting some effort into comprehending them and following provided links, it becomes a bit tiresome.

                D Offline
                D Offline
                dilkonika
                wrote on last edited by
                #7

                On your link in the clone with reflection section , contains just words.

                Cloning by Reflection uses Activator.CreateInstance to create a new object of the same type, then performs a shallow copy of each field using Reflection. The advantage of this method is it's automated and does not need to be adjusted when members are added or removed from the object. Also, it can be written to provide a deep copy. The disadvantage is it uses Reflection, which is slower and not allowed in partial trust environments.

                I'm asking because I don't know how to start this "Clone with reflection". And for your and someone other opinion about my questions, well I don't care if someone down vote my questions because I'm not in this forum to collect votes. I'm not a specialist like you , and I try to make questions as I think and hope to learn something. If someone doesn't like my questions down vote and ignore them. But I have a little opinion for you specialists ( Maybe I'm wrong , but this is my opinion ) : You judge some of my questions when I ask help how to start a thing ( like this ) and give as a response some links ( it's obvious that this are not your articles , but to someone else that wrote it ) , and on other questions where I provide my code like this http://www.codeproject.com/Messages/5036045/Make-all-the-controls-inside-a-Groupbox-unusable-w.aspx[^] you doesn't try to give an answer at all. If you like helping people just do it without comment , if you don't , down vote the questions and continue to collect votes for yourself. Until I will be I this forum I will continue to make questions ( don't care If I get response or not ) , or if you have the power , close my account and relax yourself.

                S 1 Reply Last reply
                0
                • D dilkonika

                  On your link in the clone with reflection section , contains just words.

                  Cloning by Reflection uses Activator.CreateInstance to create a new object of the same type, then performs a shallow copy of each field using Reflection. The advantage of this method is it's automated and does not need to be adjusted when members are added or removed from the object. Also, it can be written to provide a deep copy. The disadvantage is it uses Reflection, which is slower and not allowed in partial trust environments.

                  I'm asking because I don't know how to start this "Clone with reflection". And for your and someone other opinion about my questions, well I don't care if someone down vote my questions because I'm not in this forum to collect votes. I'm not a specialist like you , and I try to make questions as I think and hope to learn something. If someone doesn't like my questions down vote and ignore them. But I have a little opinion for you specialists ( Maybe I'm wrong , but this is my opinion ) : You judge some of my questions when I ask help how to start a thing ( like this ) and give as a response some links ( it's obvious that this are not your articles , but to someone else that wrote it ) , and on other questions where I provide my code like this http://www.codeproject.com/Messages/5036045/Make-all-the-controls-inside-a-Groupbox-unusable-w.aspx[^] you doesn't try to give an answer at all. If you like helping people just do it without comment , if you don't , down vote the questions and continue to collect votes for yourself. Until I will be I this forum I will continue to make questions ( don't care If I get response or not ) , or if you have the power , close my account and relax yourself.

                  S Offline
                  S Offline
                  Sascha Lefevre
                  wrote on last edited by
                  #8

                  dilkonika wrote:

                  On your link in the clone with reflection section , contains just words.

                  For me there's a link "Sample Code" following the last sentence, leading to this Codeproject-article: Base class for cloning an object in C#[^]. My point wasn't about collecting votes, neither you nor me. My point is about valuing an answer by spending some time investigating all that is mentioned in it. What is wrong with providing links to resources written by someone else as part of an answer if it's perfectly suitable for answering a part of your question? Though I like to help, somewhere has a cut to be made, else I would end up writing stuff again and again that has already been written. I'm not judging your (initial) questions. So far, those that I've seen, I think they're alright. And there's also nothing wrong with asking again if something isn't understood. But asking again if something was already covered by the previous answer or would only require following a link gives the impression that the effort of writing an answer was for naught and that's kind of disappointing. If for whatever reason the link on that webpage wasn't displayed for you (JavaScript disabled?) I'm sorry to have criticized you for that but you'll have to admit that I shouldn't have to take that rather unusual phenomenon into consideration. Also I don't regard myself an expert or specialist - it just happened that I had an answer for your current question - and I don't have an answer for your other question, otherwise I would have answered it.

                  D 1 Reply Last reply
                  0
                  • S Sascha Lefevre

                    dilkonika wrote:

                    On your link in the clone with reflection section , contains just words.

                    For me there's a link "Sample Code" following the last sentence, leading to this Codeproject-article: Base class for cloning an object in C#[^]. My point wasn't about collecting votes, neither you nor me. My point is about valuing an answer by spending some time investigating all that is mentioned in it. What is wrong with providing links to resources written by someone else as part of an answer if it's perfectly suitable for answering a part of your question? Though I like to help, somewhere has a cut to be made, else I would end up writing stuff again and again that has already been written. I'm not judging your (initial) questions. So far, those that I've seen, I think they're alright. And there's also nothing wrong with asking again if something isn't understood. But asking again if something was already covered by the previous answer or would only require following a link gives the impression that the effort of writing an answer was for naught and that's kind of disappointing. If for whatever reason the link on that webpage wasn't displayed for you (JavaScript disabled?) I'm sorry to have criticized you for that but you'll have to admit that I shouldn't have to take that rather unusual phenomenon into consideration. Also I don't regard myself an expert or specialist - it just happened that I had an answer for your current question - and I don't have an answer for your other question, otherwise I would have answered it.

                    D Offline
                    D Offline
                    dilkonika
                    wrote on last edited by
                    #9

                    Yes now I have read this example. But as I see he implement the Icloneable. there are many articles on internet that suggest avoid ICloneable because of Shallow/Deep confusion. instead , I found another way :

                    <Extension> _
                    Public Sub CopyTo(Of T)(copyFrom As T, copyTo__1 As T, copyParentProperties As Boolean)
                    Dim props As PropertyInfo()
                    If copyParentProperties Then
                    props = GetType(T).GetProperties()
                    Else
                    props = GetType(T).GetProperties(BindingFlags.[Public] Or BindingFlags.Instance Or BindingFlags.DeclaredOnly)
                    End If
                    Dim i As Integer = 0
                    While i < props.Length
                    Dim propertyValue = copyFrom.[GetType]().GetProperty(props(i).Name).GetValue(copyFrom, Nothing)
                    copyTo__1.[GetType]().GetProperty(props(i).Name).SetValue(copyTo__1, propertyValue, Nothing)
                    System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
                    End While
                    End Sub

                    But when I try to use it like this :

                            newitm = New Myobject
                            currentobj.CopyTo(newitm, False)
                            context.MyObjects.Add(Newitm)
                            context.savechanges
                    

                    I get an error on the line context.MyObjects.Add(Newitm):

                    An unhandled exception of type 'System.InvalidOperationException' occurred in System.Core.dll

                    Additional information: Collection was modified; enumeration operation may not execute.

                    (But of course , if i create a new object and fill the properties manually one by one , the ADD method works without problems. ) What may be the problem ? Thank you !

                    S 1 Reply Last reply
                    0
                    • D dilkonika

                      Yes now I have read this example. But as I see he implement the Icloneable. there are many articles on internet that suggest avoid ICloneable because of Shallow/Deep confusion. instead , I found another way :

                      <Extension> _
                      Public Sub CopyTo(Of T)(copyFrom As T, copyTo__1 As T, copyParentProperties As Boolean)
                      Dim props As PropertyInfo()
                      If copyParentProperties Then
                      props = GetType(T).GetProperties()
                      Else
                      props = GetType(T).GetProperties(BindingFlags.[Public] Or BindingFlags.Instance Or BindingFlags.DeclaredOnly)
                      End If
                      Dim i As Integer = 0
                      While i < props.Length
                      Dim propertyValue = copyFrom.[GetType]().GetProperty(props(i).Name).GetValue(copyFrom, Nothing)
                      copyTo__1.[GetType]().GetProperty(props(i).Name).SetValue(copyTo__1, propertyValue, Nothing)
                      System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
                      End While
                      End Sub

                      But when I try to use it like this :

                              newitm = New Myobject
                              currentobj.CopyTo(newitm, False)
                              context.MyObjects.Add(Newitm)
                              context.savechanges
                      

                      I get an error on the line context.MyObjects.Add(Newitm):

                      An unhandled exception of type 'System.InvalidOperationException' occurred in System.Core.dll

                      Additional information: Collection was modified; enumeration operation may not execute.

                      (But of course , if i create a new object and fill the properties manually one by one , the ADD method works without problems. ) What may be the problem ? Thank you !

                      S Offline
                      S Offline
                      Sascha Lefevre
                      wrote on last edited by
                      #10

                      dilkonika wrote:

                      there are many articles on internet that suggest avoid ICloneable because of Shallow/Deep confusion.

                      Yes, I would also avoid it. The solution is to simply name your Clone-Method/Interface differently and let its name express what it does (shallow/deep/configurable). Are you aware that the method CopyTo(..) makes a shallow copy and ignores fields? Basically the only advantage it has over Object.MemberwiseClone[^] is that you have the possibility to specify whether "parent" properties should be copied or not. So if you call it on a Student, it will copy the reference to his Result(s), not make a copy of his Result(s).

                      dilkonika wrote:

                      An unhandled exception of type 'System.InvalidOperationException' occurred in System.Core.dll Additional information: Collection was modified; enumeration operation may not execute.

                      I assume you used this code:

                              newitm = New Myobject
                              currentobj.CopyTo(newitm, False)
                              context.MyObjects.Add(Newitm)
                              context.savechanges
                      

                      in a foreach-loop where you iterated over objects (currentobj) in context? You can't modify a collection while you're iterating over it using an Enumerator (which is what a foreach-loop does). Your options: - Iterate using a for-loop, if the source collection has an indexer, in reverse direction. - Make a copy of the collection and iterate over this copy while modifying the source collection. - Create a new collection of objects to be added/deleted while iterating the source collection. When finished, add/delete the objects contained in the new collection to/from the source collection.

                      D 1 Reply Last reply
                      0
                      • S Sascha Lefevre

                        dilkonika wrote:

                        there are many articles on internet that suggest avoid ICloneable because of Shallow/Deep confusion.

                        Yes, I would also avoid it. The solution is to simply name your Clone-Method/Interface differently and let its name express what it does (shallow/deep/configurable). Are you aware that the method CopyTo(..) makes a shallow copy and ignores fields? Basically the only advantage it has over Object.MemberwiseClone[^] is that you have the possibility to specify whether "parent" properties should be copied or not. So if you call it on a Student, it will copy the reference to his Result(s), not make a copy of his Result(s).

                        dilkonika wrote:

                        An unhandled exception of type 'System.InvalidOperationException' occurred in System.Core.dll Additional information: Collection was modified; enumeration operation may not execute.

                        I assume you used this code:

                                newitm = New Myobject
                                currentobj.CopyTo(newitm, False)
                                context.MyObjects.Add(Newitm)
                                context.savechanges
                        

                        in a foreach-loop where you iterated over objects (currentobj) in context? You can't modify a collection while you're iterating over it using an Enumerator (which is what a foreach-loop does). Your options: - Iterate using a for-loop, if the source collection has an indexer, in reverse direction. - Make a copy of the collection and iterate over this copy while modifying the source collection. - Create a new collection of objects to be added/deleted while iterating the source collection. When finished, add/delete the objects contained in the new collection to/from the source collection.

                        D Offline
                        D Offline
                        dilkonika
                        wrote on last edited by
                        #11

                        Thank you ! No , I heaven;t used my code in a for-each loop. currentobj=context.myobjects.firstordefault. and after continue with the code I posted.

                        S 1 Reply Last reply
                        0
                        • D dilkonika

                          Thank you ! No , I heaven;t used my code in a for-each loop. currentobj=context.myobjects.firstordefault. and after continue with the code I posted.

                          S Offline
                          S Offline
                          Sascha Lefevre
                          wrote on last edited by
                          #12

                          Could be a quirk in EF. Please try this (two lines switched):

                                  newitm = New Myobject
                                  context.MyObjects.Add(newitm)
                                  currentobj.CopyTo(newitm, False)
                                  context.savechanges
                          
                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups