Replicate an entity

Posts   
 
    
jimph
User
Posts: 63
Joined: 06-Jun-2013
# Posted on: 16-Aug-2013 00:34:16   

Hi, I would like to create a new entity from an existing entity having a large number of fields, with the intention to copy many of the fields from the existing entity to the new entity while supplying new values for some of the fields.

What I did was 1) fetch the existing entity using its Id, 2) make change to one of the fields, leaving the Id field alone, 3) set its IsNew attribute to true, 4) and calling adapter.SaveEntity(myEntity, true).

All the values seen in the original entity are not seen when refetching the entity (which is now a new entity with new Id), only the values that I modified can be seen after fetching.

Please is there a way to mark all fields in the entity as dirty before calling SaveEntity(), I am using Adapter.

Thanks jp

jimph
User
Posts: 63
Joined: 06-Jun-2013
# Posted on: 16-Aug-2013 00:56:28   

I realized that I could set each of the field IsChanged attr to true and get them to save in the new entity, but I have many millions of rows and this would hurt badly. Is there something that I can set at the entity level (rather than individual fields).

Thanks jp

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 16-Aug-2013 06:58:44   

It's necessary to mark the fields as changed. Another option is to use a CloneHelper that do that for you, even with deep graphs. See this: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=7568

David Elizondo | LLBLGen Support Team
jimph
User
Posts: 63
Joined: 06-Jun-2013
# Posted on: 16-Aug-2013 15:02:08   

Hi daelmo, I am not so sure this makes a whole lot of sense as I have already marked an object to IsNew, which logically means that it fields must all be persisted (what does IsChanged really mean for a field of a new object (never got persisted before)?).

I thought the API should persist all the fields as specified when IsNew is set for the object. What do you think?

There is a protected function called MarkFieldsAsDirty() in one of the base class that sounds like it could do this behind the scene (but I can't access itsimple_smile

Thanks jp

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 17-Aug-2013 08:49:26   

That .IsNew=true_statement should take all DBValues and set them to null or set all [i]Fields.IsChanged_ to true might seems like obvious to you, because you expect that, but in fact, it migh be ambiguous. Some field of your entity has the same value on CurrentValue and DBValue, so from that point of view, the field is not changed, then you set the .IsNew to true, but the DBValue and Current value are the same. What if you want the entity back to IsNew=false?

Changing the .IsNew and .IsChanged properties is actually a hack, because you are cheating the framework. You could use the code posted in the link I gave you above. You also could access the MarkFieldsAsDirty method on CommonEntityBase custom code class (generated code).

David Elizondo | LLBLGen Support Team
jimph
User
Posts: 63
Joined: 06-Jun-2013
# Posted on: 17-Aug-2013 20:22:54   

Good to know your perspective, we do like things this and that for the problem at hand but not necessary best thing for the framework as the wholesimple_smile

MarkFieldsAsDirty() did not do what I hope for (not sure what it does), the fields did not get saved after setting IsNew and calling MarkFieldsAsDirty(). That is, I still need to set all fields as hasChanged() in order for them to be persisted.

We dont exactly want to clone as we just need to push the records, millions of them, to the database and done with.

Thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39912
Joined: 17-Aug-2003
# Posted on: 19-Aug-2013 17:31:57   

jimph wrote:

Good to know your perspective, we do like things this and that for the problem at hand but not necessary best thing for the framework as the wholesimple_smile

MarkFieldsAsDirty() did not do what I hope for (not sure what it does), the fields did not get saved after setting IsNew and calling MarkFieldsAsDirty(). That is, I still need to set all fields as hasChanged() in order for them to be persisted.

True, it marks the FIelds object as Dirty, but not the fields inside it, this is mostly needed for IEditableObject, so not of use for your scenario.

We dont exactly want to clone as we just need to push the records, millions of them, to the database and done with. Thanks

So in short, you want to do INSERT INTO Table1 SELECT f1, f2,..., fn FROM Table1 WHERE.... where the SELECT fetches the rows to insert but you specify different values for some fields? The question of course is: the values you want to change, are these values which are determinable inside the projection, so based on the values of the row, or are these values you have to read from somewhere else? If the former, you can specify a single INSERT statement to perform what you want. If the latter, you have to do it on the client, and indeed have to fetch the entities, copy the values you want, and re-insert the entity. Doing it on the client is likely going to be time consuming when you have to process millions of rows.

Could you elaborate a bit about the values you need changing and how the values you change are determined? because it's wise to go for the INSERT... SELECT statement (which we don't support out of the box, but you can define an IActionQuery to execute it) which runs once and which will copy your rows in 1 go on the DB server (so it will be much much faster)

Frans Bouma | Lead developer LLBLGen Pro
jimph
User
Posts: 63
Joined: 06-Jun-2013
# Posted on: 20-Aug-2013 09:52:12   

Hi, thank you for discussing my problem.

The changes will be done on the client side as you mentioned. Once the rows are fetched they will be presented in different GUIs for which the user will be able to make changes to (we have no control over this). For example he could select a node (which itself in turn contains many children, which then contain other children, etc.), he then apply some changes that will be reflected in all objects associated with the node. Sometime the changes can be calculated algorithmicallym. The objects that were changed will be saved as new objects (the old ones will not be changed and stay where they are).

jp

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39912
Joined: 17-Aug-2003
# Posted on: 21-Aug-2013 13:31:46   

ok. The new versions of the entities, are they seen as new entities or the same entities with a different version? Because if the latter, you might want to use triggers and simply update the entity, and in the update trigger copy the original row over to a history table.

Anyway, changing the values and then setting IsNew to true, and all IsChanged flags on the fields which should be inserted should work. It's essential IsNew is set to true. If you don't set IsChanged to true for a field, it will get NULL as the value in the DB.

Use entity.Fields.SetIsChanged(index, value) to avoid creating field objects.

If your code doesn't do what's expected, please post your method which should insert an existng entity as a new one.

Frans Bouma | Lead developer LLBLGen Pro