Clone an object as new entity

Posts   
 
    
jeffkararo
User
Posts: 76
Joined: 06-Jan-2004
# Posted on: 02-Sep-2004 20:25:47   

I have a scheduling application where I allow the user to enter information in for a single day and allow them to save that appointment on a daily/weekly/monthly/annual basis. I am using self-servicing. I save the first appointment and then change the date (no problem) and try to set the ID to 0 or null (in order to signify an Add/Insert for the Save method) but get an error that I cannot change the primary key. I can understand why this error is there and wouldn't want to change it. However, how can I accomplish my task of a unique ID for each appointment. I tried to find a Copy() or Clone() method but none existed. I have a lot of properties/collections in my Appointment object and don't want to do a 1 for 1 copy of all the properties and collections in the code. Any ideas on how I can accomplish this?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39880
Joined: 17-Aug-2003
# Posted on: 02-Sep-2004 20:54:56   

CustomerEntity sourceCustomer = new CustomerEntity("CHOPS"); CustomerEntity cloneCustomer = new CustomerEntity(); cloneCustomer.Fields = sourceCustomer.Fields.Clone();

should do the trick. simple_smile no related entities are copied though, just the entity's fields.

Frans Bouma | Lead developer LLBLGen Pro
jeffkararo
User
Posts: 76
Joined: 06-Jan-2004
# Posted on: 02-Sep-2004 21:11:54   

Otis wrote:

CustomerEntity sourceCustomer = new CustomerEntity("CHOPS"); CustomerEntity cloneCustomer = new CustomerEntity(); cloneCustomer.Fields = sourceCustomer.Fields.Clone();

should do the trick. simple_smile no related entities are copied though, just the entity's fields.

I don't see a Clone() method off of the Fields collection. I get a compile error.

 'SD.LLBLGen.Pro.ORMSupportClasses.IEntityFields' does not contain a definition for 'Clone'

And will this remove the primary key or set it to 0 in order to signify an "add" to the Save() method?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39880
Joined: 17-Aug-2003
# Posted on: 02-Sep-2004 21:28:13   

jeffkararo wrote:

Otis wrote:

CustomerEntity sourceCustomer = new CustomerEntity("CHOPS"); CustomerEntity cloneCustomer = new CustomerEntity(); cloneCustomer.Fields = sourceCustomer.Fields.Clone();

should do the trick. simple_smile no related entities are copied though, just the entity's fields.

I don't see a Clone() method off of the Fields collection. I get a compile error.

Oh sorry my bad simple_smile Fields returns IEntityFields of course, it's in the class, not in teh interface: cloneCustomer.Fields = ((EntityFields)sourceCustomer.Fields).Clone();

And will this remove the primary key or set it to 0 in order to signify an "add" to the Save() method?

it will deepcopy the fields (and thus the values) of the entity, and therefore the cloned entity will have the same values. It will however have IsNew set to true. You can't save it also, as no field is changed, so nothing will be saved. Set all field's IsChanged flag to true and the Fields.IsDirty to true.

Frans Bouma | Lead developer LLBLGen Pro
jeffkararo
User
Posts: 76
Joined: 06-Jan-2004
# Posted on: 02-Sep-2004 22:39:50   

Your code works but not as I want it to. I need to have the primary key nulled out in order to add a new record for the table. The ID remains the same in the new entity and when i go to save the new entity, it just overwrites the record in the DB with the same ID instead of adding a new record to the table. Even setting IsNew = true and IsDirty = true does not help. The data from the old entity is overwritten with the new entity. I don't want it overwritten, I want a new record with all the same data except for the ID, which is the primary key.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39880
Joined: 17-Aug-2003
# Posted on: 02-Sep-2004 23:24:41   

jeffkararo wrote:

Your code works but not as I want it to. I need to have the primary key nulled out in order to add a new record for the table. The ID remains the same in the new entity and when i go to save the new entity, it just overwrites the record in the DB with the same ID instead of adding a new record to the table. Even setting IsNew = true and IsDirty = true does not help. The data from the old entity is overwritten with the new entity. I don't want it overwritten, I want a new record with all the same data except for the ID, which is the primary key.

Is it an identity field? It doesn't matter what the column's value is, if it's an identity column, the field is not inserted, so be sure to set IsNew to true.

Frans Bouma | Lead developer LLBLGen Pro
jeffkararo
User
Posts: 76
Joined: 06-Jan-2004
# Posted on: 03-Sep-2004 00:33:48   

Otis wrote:

[Is it an identity field? It doesn't matter what the column's value is, if it's an identity column, the field is not inserted, so be sure to set IsNew to true.

Yes, it is an identity field that the SQL server will auto increment. I did set IsNew = true on the object and set IsDirty = true for all the fields. Do I set IsNew = true for the identity field or do I need to set IsNew = true for all the fields?

What if I just set IsNew = true on the existing object and then save it again instead of cloning it into a new object? Wouldn't that work as well?

Thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39880
Joined: 17-Aug-2003
# Posted on: 03-Sep-2004 09:46:54   

jeffkararo wrote:

Otis wrote:

[Is it an identity field? It doesn't matter what the column's value is, if it's an identity column, the field is not inserted, so be sure to set IsNew to true.

Yes, it is an identity field that the SQL server will auto increment. I did set IsNew = true on the object and set IsDirty = true for all the fields. Do I set IsNew = true for the identity field or do I need to set IsNew = true for all the fields?

You set the IsNew flag on teh entity, it's for telling the save logic to perform an INSERT instead of an UPDATE.

What if I just set IsNew = true on the existing object and then save it again instead of cloning it into a new object? Wouldn't that work as well?

Good point, it should work, your object will then hold the new entity after the save. Be sure to set the IsChanged flags on the fields: for(int i=0;i<myEntity.Fields.Count;i++) { myEntity.Fields[i].IsChanged=true; } myEntity.IsNew=true; myEntity.Save();

Frans Bouma | Lead developer LLBLGen Pro
jeffkararo
User
Posts: 76
Joined: 06-Jan-2004
# Posted on: 03-Sep-2004 17:13:12   

It did work - no need to clone the fields just set the appropriate flags and it is brand new.

Thanks

maird
User
Posts: 10
Joined: 24-Jan-2006
# Posted on: 30-Jan-2006 17:31:38   

I'm trying to use this method and it seems to work...mostly. the only thing that i find wierd is that the primary key field (an identity column) doesn't get updated with the new value. is this on purpose? is there any way to work around this?

bclubb
User
Posts: 934
Joined: 12-Feb-2004
# Posted on: 31-Jan-2006 02:25:55   

Is it auto-incremented. I believe the code is relying on the sql server to write the value for the field.

Andrius
User
Posts: 68
Joined: 04-Apr-2005
# Posted on: 01-Feb-2006 12:22:00   

Otis wrote:

CustomerEntity Oh sorry my bad simple_smile Fields returns IEntityFields of course, it's in the class, not in teh interface: cloneCustomer.Fields = ((EntityFields)sourceCustomer.Fields).Clone();

It would be really nice if IEntityFields could extend all interfaces EntityFields does. Same is true for other interfaces and classes Then we could work with interfaces instead on abstract classes, which I think is better coding practice

Andrius
User
Posts: 68
Joined: 04-Apr-2005
# Posted on: 01-Feb-2006 13:22:33   

Otis wrote:

CustomerEntity sourceCustomer = new CustomerEntity("CHOPS"); CustomerEntity cloneCustomer = new CustomerEntity(); cloneCustomer.Fields = sourceCustomer.Fields.Clone();

should do the trick. simple_smile no related entities are copied though, just the entity's fields.

Is there a way to clone entity together with child enties and child entity collections?

So far we are using binary serialization for this purpose

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39880
Joined: 17-Aug-2003
# Posted on: 02-Feb-2006 11:24:16   

Andrius wrote:

Otis wrote:

CustomerEntity Oh sorry my bad simple_smile Fields returns IEntityFields of course, it's in the class, not in teh interface: cloneCustomer.Fields = ((EntityFields)sourceCustomer.Fields).Clone();

It would be really nice if IEntityFields could extend all interfaces EntityFields does. Same is true for other interfaces and classes Then we could work with interfaces instead on abstract classes, which I think is better coding practice

I thought that too, so did MS back in 2003, but they moved towards base classes and away from interfaces. One of the reasons was that an interface can't be updated without breaking code, but a class can.

What they do today is implement as much interfaces explicitly and call from those methods into normal methods offered by the class itself.

I overdid the interface design in the framework a bit, which is caused by the fact that I first designed all the interfaces and then wrote code. The interfaces for entityfields and entityfield for example aren't that required, there's just 1 implementor.

So to recap: the interfaces should offer you a type definition which is a subset of the class type's interface. It's therefore not always wise to simply make an llblgen pro interface inherit from all interfaces defined on its implementor, as that's not always known. (in this case, it is, but it doesn't have to).

In this particular case the cast to the actual implementing type to be able to perform a clone is mitigating the purpose of the interface, which I agree with. However to keep the interfaces offer just the functionality the type represented by the interface should offer, I've to decide this on a type by type basis.

I'll try to make the proper decision which interfaces to inherit from for v2.0 so using interfaces is as painless as can be. Interfaces are sometimes required for generic programming with generics, how ironic that may sound, because generic code using generic types like an EntityCollection<T> also has to know what T is, which can create a huge complexity inside the code, as using IEntityCollection2 is much simpler.

Andrius wrote:

Otis wrote:

CustomerEntity sourceCustomer = new CustomerEntity("CHOPS"); CustomerEntity cloneCustomer = new CustomerEntity(); cloneCustomer.Fields = sourceCustomer.Fields.Clone(); should do the trick. simple_smile no related entities are copied though, just the entity's fields.

Is there a way to clone entity together with child enties and child entity collections? So far we are using binary serialization for this purpose

No, sorry. Cloning is per entity.

Frans Bouma | Lead developer LLBLGen Pro
Andrius
User
Posts: 68
Joined: 04-Apr-2005
# Posted on: 23-Feb-2006 13:58:27   

Otis wrote:

Andrius wrote:

Otis wrote:

CustomerEntity sourceCustomer = new CustomerEntity("CHOPS"); CustomerEntity cloneCustomer = new CustomerEntity(); cloneCustomer.Fields = sourceCustomer.Fields.Clone(); should do the trick. simple_smile no related entities are copied though, just the entity's fields.

Is there a way to clone entity together with child enties and child entity collections? So far we are using binary serialization for this purpose

No, sorry. Cloning is per entity.

Do you have any plans to make it? I believe it can become handy in some situations. And there is not much effort to do it.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39880
Joined: 17-Aug-2003
# Posted on: 23-Feb-2006 14:55:11   

It's on the TODO, as it's requested a lot. How and when it is added isn't decided yet.

Frans Bouma | Lead developer LLBLGen Pro
LLBLGen
User
Posts: 43
Joined: 10-Apr-2006
# Posted on: 29-Dec-2006 19:15:58   

It's on the TODO, as it's requested a lot. How and when it is added isn't decided yet.

I was just wondering if it is comming soon...(Cloning EntityCollection) or there is already one?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39880
Joined: 17-Aug-2003
# Posted on: 30-Dec-2006 17:42:30   

It was on the list for v2.0, but we decided it wouldn't be feasable to add it. The thing is that there is a proper clone routine in the entityfields(2) classes, so with the factory at hand you can create new entities without a problem.

Frans Bouma | Lead developer LLBLGen Pro