THESE FORUMS ARE NOW FROZEN
Please choose "Forums" from the Main menu of www.entityspaces.net to get to our new forums.

Clone/Copy entity using serialization not working

rated by 0 users
This post has 13 Replies | 3 Followers

Top 100 Contributor
Posts 22
sqrbox Posted: 09-12-2007 8:21 AM

Hello,

I tried to copy an entity object using the binaryformatter, however before saving I need to change the primary key to another value. This attempt produces an error.

Here is my code:

            BinaryFormatter bf = new BinaryFormatter(); 
            MemoryStream ms = new MemoryStream(); 
  
            //Copy Quiz
            BusinessObjects.QuizModule fromquiz = new BusinessObjects.QuizModule();
            fromquiz.LoadByPrimaryKey(int.Parse(fromNodeID));

            bf.Serialize(ms, fromquiz);
            ms.Position = 0;
            BusinessObjects.QuizModule toquiz = new BusinessObjects.QuizModule();
            toquiz = (BusinessObjects.QuizModule)bf.Deserialize(ms);
            ms.Close();
            toquiz.NodeID = int.Parse(toNodeID); //Change PK id to new one
            toquiz.Save(); //Error on saving

Error and stack trace:

Incorrect syntax near the keyword 'WHERE'.

   at EntitySpaces.Core.esEntity.SaveToProvider(esSqlAccessType sqlAccessType)
   at EntitySpaces.Core.esEntity.Save(esSqlAccessType sqlAccessType)
   at EntitySpaces.Core.esEntity.Save()
   at PPCS.modules.QuizModule.CopyModuleContent(String fromNodeID, String toNodeID) in C:\Documents and Settings\pixel\My Documents\Visual Studio 2005\Projects\PPCS\modules\QuizModule.ascx.cs:line 66
  

I tried to figure out another way to copy an entity by iterating through columns, but the es.Meta.Columns is read only???

So, I can't do this: toquiz.es.Meta.Columns[ i ] = fromquiz.es.Meta.Columns[ i ];

Please, help. Thanks!

 

Top 10 Contributor
Posts 905
EntitySpaces by design does not support updating of a primary key.

Regards, Scott Schecter EntitySpaces | Blog | Twitter

Top 10 Contributor
Posts 3,881

If your goal is to merely clone a record and not actually change the primary key of an existing record you might try this:

Code:
Business bus = new Business();
if (bus.LoadByPrimaryKey("41"))
{
    bus.BusinessId = "42";
    bus.AcceptChanges();
    bus.es.RowState = DataRowState.Added;
    bus.Save();
}

 

I didn't test it but it should work, above I load business "41" and save it under a new primary key "42" 

 

EntitySpaces | Twitter | BLOG | Please honor our Software License

Top 10 Contributor
Posts 762

Hi

I think the intention is to create a new entity but copy the values across from an existing one - if that's the case then something like the following might help - could do with tyding up of course but it will point you in the right direction:

Code:
    Private Sub CreateCopyOfEntityWithoutPK()
        Dim original As New Contact
        Dim copy As New Contact
        original.LoadByPrimaryKey(65630)

        For Each c As EntitySpaces.Interfaces.esColumnMetadata In original.es.Meta.Columns
            If Not c.IsInPrimaryKey Then
                copy.SetColumn(c.PropertyName, original.GetColumn(c.PropertyName))
            End If
        Next

End Sub

 

Hope that helps

Martin

Top 10 Contributor
Posts 3,881

Ya, agreed, that is what my sample should do as well, it basically reads it and recommits with a new PK. However, your example ought to work as well.  Thanx Martin, that would make a pretty generic clone method ?

sqrbox, Let's know how you solve this ....

EntitySpaces | Twitter | BLOG | Please honor our Software License

Top 10 Contributor
Posts 762

Of course your code would do the same Mike - brain slipped gear for a second there ;)

As for my code making a generic clone type method, don't see why not - if it's helpful for people they can use it as they wish (although I'm sure there are cleaner ways of achieving the same thing).

Cheers

Martin

Top 10 Contributor
Posts 478

I think this works, because I am already using this way. try this:

Put this function somewhere. I put this function in a Util Class.  
Code:
1    #region Clone
2            /// <summary>
3            ///  Clona um objeto passado.
4            /// </summary>
5            /// <param name="objetoClonar"></param>
6            /// <returns>Novo objeto clonado</returns>
7            public static Object Clone(Object objetoClonar)
8            {
9                // Serialize 
10               BinaryFormatter bf = new BinaryFormatter();
11               MemoryStream ms = new MemoryStream();
12               bf.Serialize(ms, objetoClonar);
13   
14               // Deserialize into a new entity 
15               ms.Position = 0;
16               Object objetoClonado = bf.Deserialize(ms);
17               ms.Close();
18   
19               return objetoClonado;
20           }
21   #endregion

then in your class do this: 

Code:
1    Employee employee = new Employee ();
2    employee .LoadByPrimaryKey(1);
3    
4    //
5    Employee employeeCopy = (Employee) Util.Clone(employee);
6    employeeCopy.id = 2;
7    employeeCopy.Save();
     
    
I don't test exactly this way, but I think it works.
The diference to your first code is that another object is created and returned. try this and let me know if works.
 

 

Top 10 Contributor
Posts 478
If the example above is not working try add line 7 after you change the primary key.  
Code:
1    Employee employee = new Employee ();
2    employee .LoadByPrimaryKey(1);
3      
4    //
5    Employee employeeCopy = (Employee) Util.Clone(employee);
6    employeeCopy.id = 2;
7    employeeCopy.AcceptChanges();
8    employeeCopy.Save(); 
Top 100 Contributor
Posts 22

Well, I tried the serialization code again with AcceptChanges() and it doesn't give an error, but no new data get persisted into the table.

I tried  Mike Griffin's code in thread 5059. It gives an insert error.

So, I'm resorting to manually copying the value and changing the primary key and this works fine:

            BusinessObjects.QuizModule toquiz = new BusinessObjects.QuizModule();
            toquiz.NodeID = int.Parse(toNodeID);
            toquiz.Points = fromquiz.Points;
            toquiz.RandomizeAnswers = fromquiz.RandomizeAnswers;
            toquiz.RandomizeQuestions = fromquiz.RandomizeQuestions;
            toquiz.Save();

 This is the only place I'm changing the PK, maybe I have to rethink how I approach this table.

 Thank you for all of the replies!
 

Top 10 Contributor
Posts 762
Hi Out of interest, did you try my suggestion for copying the columns across - just wondered whether that worked for you or not Cheers Martin
Top 100 Contributor
Posts 22

Hmmm..., now I think the serialization/deserialization does not work at all for copying an entity object.

After my last post, I tried to use the serialization to clone a different entity object without changing the PK, the entity got copied and get a new identity PK, but I'm getting NULL values for all of the non-PK columns.

Martin, sorry I didn't get a chance to try your code for copying the column across, I'll try it after this post.

The entityspaces version: 2007.0.901.0, and I'm using MS SQL 2000 + ASP .NET2.0 .
 

Top 100 Contributor
Posts 22

Martin's code works. Yes

Now if I can figure out how to move it to a generic method I'll be set.  

Here it is in C# :
                BusinessObjects.Questions froment = new BusinessObjects.Questions();
                froment.LoadByPrimaryKey(int.Parse(fromNodeID));
                BusinessObjects.Questions toent = new BusinessObjects.Questions();
                foreach (esColumnMetadata c in froment.es.Meta.Columns)
                {
                    if (!c.IsInPrimaryKey)
                    {
                        toent.SetColumn(c.PropertyName, froment.GetColumn(c.PropertyName));
                    }
                }
                toent.Save();
 

Top 10 Contributor
Posts 762

Hi Glad it worked :D Something like the following (VB I'm afraid ;)) should do the trick:

Code:
    Private Function CreateCopyOfEntity(ByVal Entity As EntitySpaces.Core.esEntity) As EntitySpaces.Core.esEntity
        Dim copy As EntitySpaces.Core.esEntity
        For Each c As EntitySpaces.Interfaces.esColumnMetadata In Entity.es.Meta.Columns
            If Not c.IsInPrimaryKey Then
                copy.SetColumn(c.PropertyName, Entity.GetColumn(c.PropertyName))
            End If
        Next
        Return copy
    End Function
 

Cheers Martin

Top 150 Contributor
Posts 20

If your columns have underscores the PropertyName is not the original name of the column so you need to the use 'Name' property:

 

 

Code:
foreach (esColumnMetadata c in source.es.Meta.Columns)
if (!c.IsInPrimaryKey)
                {
                    rtn.SetColumn(c.Name, source.GetColumn(c.Name));
                }
            }
 
Sean Rock
Page 1 of 1 (14 items) | RSS
Copyright © 2005 - 2009, EntitySpaces, LLC