Best Way to Implement Versioning

Posts   
 
    
yin
User
Posts: 13
Joined: 23-Feb-2006
# Posted on: 23-Feb-2006 18:37:23   

Sirs,

What is the best approach to implementing versioning without breaking LLBGen?. We have entities with unique integer PKs and a second 'version' column.

the generated code saves the first version no problem but tends to struggle with updating this version and saving subsequent versions. The worst problem appears to be copying the head version to make a 'new version'. You see our head version always has version 999999 and subsequent versions have lower numbers.

Please point me in the correct direction, am sure the tool can manage if we just make the tables the correct shape.

Thanks

i

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 23-Feb-2006 21:50:50   

If you are doing audit tracking, I would implement this in a trigger.

If the trigger isnt an option and youre using adapter pattern, could you do something like the pseudo code below?:

void DoWork() { UnitOfWork2 uow = new UnitOfWork2(); SomeEntity head = new SomeEntity(); adapter.FetchEntity(head, HeadPredicate(primaryKey));

int headId = head.Id;

uow.AddForSave(NewVersion(head)); uow.AddUpdateEntitiesDirectlyCall(OldVersion(head), HeadPredicate(headId)); uow.Commit(); }

RelationPredicateBucket HeadBucket(int primaryKey) { // build and return a predicate for the version being updated to the old version}

// copies values from the fetched head into a new entity IEntity2 OldVersion(SomeEntity head) { SomeEntity oldVersion = NewVersion(head); oldVersion.VersionNumber = NextVersionNumber(); oldVersion.IsNew = true; return oldVersion; }

// copes the head into a new entity and sets the version so that the // newly created entity is the latest version IEntity2 NewVersion(SomeEntity head) { // modify the original head SomeEntity newVersion = new SomeEntity(); // set the rest of the fields newVersion.field1 = head.field1; newVersion.field2 = head.field2; newVersion.Version = 999999; return newVersion; }

yin
User
Posts: 13
Joined: 23-Feb-2006
# Posted on: 24-Feb-2006 09:24:45   

thanks for the suggestion.

Turns out i was setting new After setting the instrument id. got it the right way around. and Bingo!

there may have been some inconsistency between the cataloge and the model too. regenerated all that. seems all ok : )

Cheers!


here is other stuff i wrote but it matters less now::

Have been trying the same thing in SelfServicing, however the generated code seemed to have some trouble doing the inserts. I wonder if there is any significant difference between SS and Adapters?

I'm going to work through it again as I'm not really familiar with the API and may have made some error. Might run it through once more using adapters but don't have that much time, need to get this production soon.

Versioning with triggers is not attractive as we would like to include the history in some selects without having to 'butcher' the SQL too much. The separate audit tables are not good for that. Of course I could write triggers that insert into the same table. A slightly scary option, especiallly as there is a 1-1 relationship between the child (subtype) and parent key (supertype).

Yes, that's where it all seems to get too much. Auditing a subclass relationship into the same table is perhaps too much to ask of the generated code. That's when I started to think that if i did the auditing exactly the way the code expects, it might work a little better.

Another option is to get rid of the composite key (id, version) and make the primary key of the tables just an int with the (id, version) as a subkey. This might work, it will be tricky to persuade the framework to reconstruct the relationships though. I would want all the (id, version) relationships not the (int) relationships.

again there is not really enough time to test this out so someone who has seen this done before or has more exposure to LLBGen will have a far better idea which way to jump.

thanks

ian

ps typo??

IEntity2 OldVersion(SomeEntity head) { SomeEntity oldVersion = NewVersion(head); oldVersion.VersionNumber = NextVersionNumber();

should be

IEntity2 OldVersion(SomeEntity oldVersion) { //SomeEntity oldVersion = NewVersion(head); <-- makes oldversion same as new version oldVersion.VersionNumber = NextVersionNumber();

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 24-Feb-2006 13:58:39   

I coded this:

SomeEntity oldVersion = NewVersion(head); 

by intention because my thinking was that whenever you change the head, the data that was fetched becomes the outdated version and a new record needs to be created with version # 999999.

Therefore I create a copy of the fetched data, change the version number to whatever the next one is, and use the copy to update the original head, using the original values and the new version number.

But in anycase, I am not that familiar with the logic you need, so that was my stab. Hopefully it helped.

yin
User
Posts: 13
Joined: 23-Feb-2006
# Posted on: 02-Mar-2006 09:45:39   

Yes it helped this is a very foreign zone and all quite challenging. Thanks for volunteering.

Just not quite understanding because there are two calls to new version in sample code?

Also, why use unit of work? I would think of using transaction. Is there a problem using transactions?

thanks

Ian

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 03-Mar-2006 06:28:57   

There is no issue using your own transactions. Unit of work is a container that you add things to. When you commit the unit of work, it sorts out the proper order for inserts, updates, and deletes and wraps them into a transaction for you.

The reason that I wrote the code as i did was because I was assuming this:

Before the execution of the code, you have some entity in a table, and this entity is the current version. Lets say the entity is a name entity, and also lets assume the record looks like this:

NameId,VersionId,FirstName,LastName 501,999999,Joe,Bloggs

Now, I also assumet that you want to change this name, and at the same time keep the old version in the table. I think my code would update record 501, and create a new entity. So lets say that you change Joe to John, the data in the table should look like this.....

NameId,VersionId,FirstName,LastName 501,85,Joe,Bloggs 502,999999,John,Bloggs

85 is the next version # (i just picked an arbitrary number).

So now, I assumed that if you change the last name of the current version to Smith, your data in your table would look like this:

NameId,VersionId,FirstName,LastName 501,85,Joe,Bloggs 502,86,John,Bloggs 503,999999,John,Smith

Also, regarding multiple calls, to NewVersion, this simply copies the data from the fetched head entity into a new entity and returns the new entity. The old version is just a copy of the existing data, except for the version number, so I call into the NewVersion method and set the version number to the next version number. I use the entity returned from oldVersion to update the existing row in the db and I create a new data row using the entity returned from newVersion.

It is possible that I dont fully understand what you are trying to implement.