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!
Regards, Scott Schecter EntitySpaces | Blog | Twitter
If your goal is to merely clone a record and not actually change the primary key of an existing record you might try this:
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
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:
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
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 ....
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
I think this works, because I am already using this way. try this:
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:
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.
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();
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!
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 .
Martin's code works.
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();
Hi Glad it worked :D Something like the following (VB I'm afraid ;)) should do the trick:
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
If your columns have underscores the PropertyName is not the original name of the column so you need to the use 'Name' property:
foreach (esColumnMetadata c in source.es.Meta.Columns) if (!c.IsInPrimaryKey) { rtn.SetColumn(c.Name, source.GetColumn(c.Name)); } }