Re: [vwnc] Commitments without update

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

jtuchel
Hi Marten,

Where does aSharedConfig come from? If the result of getGlorpSession is a new Session, you`d have to registerAsOld: if you know the object is already in the database.

Just a short hint: if a Session registers an object, it will always assune it is new, unless it already is in its caches at register time. A session does its bokkeeping by caching all registered objects, and an object is either registered when it is read from the db, or when you register it. Every session does keep its own cache(undoMap).

Hth,

Joachin

[hidden email] schrieb:

Hi,

It looks like Glorp really doesn't like to commit a registered object which basically has not been updated.

 

10 timesRepeat:

[self getGlorpSession inUnitOfWorkDo:

[self getGlorpSession register: aSharedConfig


"Do nothing really"]].

 

Whenever this happens it wants to create a new object with the same primary key.

Why ?

Regards,

@+Maarten,

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

jtuchel
Hi again,

Re: the same primary key. Is this consisting of attributes of the object, or do you use sequences? In the first case, this is logical, the latter case would need a bit of digging into your code....

[hidden email] schrieb:

Hi,

It looks like Glorp really doesn't like to commit a registered object which basically has not been updated.

 

10 timesRepeat:

[self getGlorpSession inUnitOfWorkDo:

[self getGlorpSession register: aSharedConfig


"Do nothing really"]].

 

Whenever this happens it wants to create a new object with the same primary key.

Why ?

Regards,

@+Maarten,

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

Maarten Mostert
In reply to this post by jtuchel

Hi Kartsen and Joachim,

I use a unique Glorp session in my application of which getGlorpSession is the accessor method.

The SharedConfig Object is very simple object that doesn't hold any links to other objects and the table will allways contain one single row with id 1.

As it names said it holds some parameters that needs to be shared among other users like which day is a weekend day or how many hours a workday contains. In this particular case I am loading an MS Project file which agenda potentially modifies the SharedConfig object. The first time I load the file into my application all goes fine. If I load the file a second time shortly after it will hit the primary key error as nothing has been updated.

Lets notice that I've experienced primary key errors at many many occasions but it allways remained unpredictable as it often concerned other linked Objects and seemed vaguely related to the cache policy. It is the same problem I talked about to Nial and Tom during the last ESUG, but until now I never managed to reproduce it on a simple case.

 

Joachim you mention to use registerAsOld: honestly I never heard about that, are you meaning the private one ?

 

privateRegisterAsOld: anObject

"Register the object as something we already read from the database, skipping the isNew: test. Private! Normally you would just use register:"

| realObject |

currentUnitOfWork isNil ifTrue: [^self].

realObject := self realObjectFor: anObject ifNone: [^self].


 

currentUnitOfWork register: realObject

 

 

Obviously in this simple case I can easily work around the problem but I have hundreds of register: methods elsewhere in my application, so it would be good to know the intended policy here.

 

Regards,

 

Maarten,

 

classModelForSharedConfig: aClassModel


aClassModel newAttributeNamed: #id.

aClassModel newAttributeNamed: #current_version. "Float"

aClassModel newAttributeNamed: #descriptor_version.   "String"

aClassModel newAttributeNamed: #organisation_update type: Integer.

aClassModel newAttributeNamed: #hierarchy_update type: Integer.

aClassModel newAttributeNamed: #relations_update type: Integer.

aClassModel newAttributeNamed: #tablecreation type: Timestamp.

aClassModel newAttributeNamed: #weekendsunday type: Boolean.

aClassModel newAttributeNamed: #weekendmonday type: Boolean.

aClassModel newAttributeNamed: #weekendtuesday type: Boolean.

aClassModel newAttributeNamed: #weekendwednesday type: Boolean.

aClassModel newAttributeNamed: #weekendthursday type: Boolean.

aClassModel newAttributeNamed: #weekendfriday type: Boolean.

aClassModel newAttributeNamed: #weekendsaturday type: Boolean.

aClassModel newAttributeNamed: #secondsperday type: Integer

 

 

> "Joachim Tuchel" <[hidden email]> |

Hi again,

Re: the same primary key. Is this consisting of attributes of the object, or do you use sequences? In the first case, this is logical, the latter case would need a bit of digging into your code....

[hidden email] schrieb:

Hi,

It looks like Glorp really doesn't like to commit a registered object which basically has not been updated.

 

10 timesRepeat:

[self getGlorpSession inUnitOfWorkDo:

[self getGlorpSession register: aSharedConfig


"Do nothing really"]].

 

Whenever this happens it wants to create a new object with the same primary key.

Why ?

Regards,

@+Maarten,

 

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

Maarten Mostert
In reply to this post by jtuchel

To complement,

 

I open a new instance of my application and inserted the following fragment of Code in my aplication when opening a file.

 

1 to: 1000

do:

[:m |  Transcript show:'Register aSharedConfig ',m printString;cr.

self getGlorpSession

inUnitOfWorkDo: [self getGlorpSession register: aSharedConfig]].

 

 

This time it runs fine, I repeat the operation 6, 7 times without any problems, meaning at 6000 succesfull registration of an unchanged Object after opening a session.

 

Then I wait for maybe half an hour or maybe something more. I again open the file and run the above mentioned.

 

This time it produces the key duplicate error on the first register: (m =1) with the enclosed errorLog.

 

https://dl.dropboxusercontent.com/u/5848367/Error%20log ???

 

Personally I can only thing of some automatic cache behaviour which after a certain time consideres the Object to be a new Object. I don't know what else could come up with a different behaviour only after a certain time.

 

 

Regards,

 

Maarten,

 

 

 

> [hidden email] |

Hi Kartsen and Joachim,

I use a unique Glorp session in my application of which getGlorpSession is the accessor method.

The SharedConfig Object is very simple object that doesn't hold any links to other objects and the table will allways contain one single row with id 1.

As it names said it holds some parameters that needs to be shared among other users like which day is a weekend day or how many hours a workday contains. In this particular case I am loading an MS Project file which agenda potentially modifies the SharedConfig object. The first time I load the file into my application all goes fine. If I load the file a second time shortly after it will hit the primary key error as nothing has been updated.

Lets notice that I've experienced primary key errors at many many occasions but it allways remained unpredictable as it often concerned other linked Objects and seemed vaguely related to the cache policy. It is the same problem I talked about to Nial and Tom during the last ESUG, but until now I never managed to reproduce it on a simple case.

 

Joachim you mention to use registerAsOld: honestly I never heard about that, are you meaning the private one ?

 

privateRegisterAsOld: anObject

 

"Register the object as something we already read from the database, skipping the isNew: test. Private! Normally you would just use register:"

| realObject |

currentUnitOfWork isNil ifTrue: [^self].

realObject := self realObjectFor: anObject ifNone: [^self].


 

currentUnitOfWork register: realObject

 

 

Obviously in this simple case I can easily work around the problem but I have hundreds of register: methods elsewhere in my application, so it would be good to know the intended policy here.

 

Regards,

 

Maarten,

 

classModelForSharedConfig: aClassModel

 


aClassModel newAttributeNamed: #id.

aClassModel newAttributeNamed: #current_version. "Float"

aClassModel newAttributeNamed: #descriptor_version.   "String"

aClassModel newAttributeNamed: #organisation_update type: Integer.

aClassModel newAttributeNamed: #hierarchy_update type: Integer.

aClassModel newAttributeNamed: #relations_update type: Integer.

aClassModel newAttributeNamed: #tablecreation type: Timestamp.

aClassModel newAttributeNamed: #weekendsunday type: Boolean.

aClassModel newAttributeNamed: #weekendmonday type: Boolean.

aClassModel newAttributeNamed: #weekendtuesday type: Boolean.

aClassModel newAttributeNamed: #weekendwednesday type: Boolean.

aClassModel newAttributeNamed: #weekendthursday type: Boolean.

aClassModel newAttributeNamed: #weekendfriday type: Boolean.

aClassModel newAttributeNamed: #weekendsaturday type: Boolean.

aClassModel newAttributeNamed: #secondsperday type: Integer

 

 

 

> "Joachim Tuchel" <[hidden email]> |

Hi again,

Re: the same primary key. Is this consisting of attributes of the object, or do you use sequences? In the first case, this is logical, the latter case would need a bit of digging into your code....

[hidden email] schrieb:

Hi,

It looks like Glorp really doesn't like to commit a registered object which basically has not been updated.

 

10 timesRepeat:

[self getGlorpSession inUnitOfWorkDo:

[self getGlorpSession register: aSharedConfig


"Do nothing really"]].

 

Whenever this happens it wants to create a new object with the same primary key.

Why ?

Regards,

@+Maarten,

 

 

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

jtuchel
In reply to this post by Maarten Mostert
HI Maarten,

I've never used inUnitOfWorkDo:, so I may be a bit off with my comments...

First of all: yes, I was talking about what seems to be named privateRegisterAsOld: in current Glorp. In the last version that shipped with the previous VA Smalltalk, there was a method named registerAsOld: and it hat a few senders. So something has changed with this method.

As Karsten already said, you need to see if the two "versions" of your sharedConfig are the same object (#hash / #identityHash). The way I read your business case description, I would guess that is the problem. You import the file and always create a new instance of your sharedConfig object, right?

We are having a similar thing in our application: we import a list of banks and tax offices several times a year, and in our import code we always look for the existing object in the db and modify it and only create new instances and register them when there is no old one. This way we avoid duplicates. Another option would be a delete / insert combination.

This is what I guess Karsten and I suspect is happening: Your session knows the old object and gets a new one registered. Since the new one is not == the old one, it registers it as a new object and on commit it generates an insert, which fails due to duplicate keys.

Good luck,

Joachim




Am 30.01.14 23:45, schrieb [hidden email]:

Hi Kartsen and Joachim,

I use a unique Glorp session in my application of which getGlorpSession is the accessor method.

The SharedConfig Object is very simple object that doesn't hold any links to other objects and the table will allways contain one single row with id 1.

As it names said it holds some parameters that needs to be shared among other users like which day is a weekend day or how many hours a workday contains. In this particular case I am loading an MS Project file which agenda potentially modifies the SharedConfig object. The first time I load the file into my application all goes fine. If I load the file a second time shortly after it will hit the primary key error as nothing has been updated.

Lets notice that I've experienced primary key errors at many many occasions but it allways remained unpredictable as it often concerned other linked Objects and seemed vaguely related to the cache policy. It is the same problem I talked about to Nial and Tom during the last ESUG, but until now I never managed to reproduce it on a simple case.

 

Joachim you mention to use registerAsOld: honestly I never heard about that, are you meaning the private one ?

 

privateRegisterAsOld: anObject

"Register the object as something we already read from the database, skipping the isNew: test. Private! Normally you would just use register:"

| realObject |

currentUnitOfWork isNil ifTrue: [^self].

realObject := self realObjectFor: anObject ifNone: [^self].


 

currentUnitOfWork register: realObject

 

 

Obviously in this simple case I can easily work around the problem but I have hundreds of register: methods elsewhere in my application, so it would be good to know the intended policy here.

 

Regards,

 

Maarten,

 

classModelForSharedConfig: aClassModel


aClassModel newAttributeNamed: #id.

aClassModel newAttributeNamed: #current_version. "Float"

aClassModel newAttributeNamed: #descriptor_version.   "String"

aClassModel newAttributeNamed: #organisation_update type: Integer.

aClassModel newAttributeNamed: #hierarchy_update type: Integer.

aClassModel newAttributeNamed: #relations_update type: Integer.

aClassModel newAttributeNamed: #tablecreation type: Timestamp.

aClassModel newAttributeNamed: #weekendsunday type: Boolean.

aClassModel newAttributeNamed: #weekendmonday type: Boolean.

aClassModel newAttributeNamed: #weekendtuesday type: Boolean.

aClassModel newAttributeNamed: #weekendwednesday type: Boolean.

aClassModel newAttributeNamed: #weekendthursday type: Boolean.

aClassModel newAttributeNamed: #weekendfriday type: Boolean.

aClassModel newAttributeNamed: #weekendsaturday type: Boolean.

aClassModel newAttributeNamed: #secondsperday type: Integer

 

 

> "Joachim Tuchel" [hidden email] |

Hi again,

Re: the same primary key. Is this consisting of attributes of the object, or do you use sequences? In the first case, this is logical, the latter case would need a bit of digging into your code....

[hidden email] schrieb:

Hi,

It looks like Glorp really doesn't like to commit a registered object which basically has not been updated.

 

10 timesRepeat:

[self getGlorpSession inUnitOfWorkDo:

[self getGlorpSession register: aSharedConfig


"Do nothing really"]].

 

Whenever this happens it wants to create a new object with the same primary key.

Why ?

Regards,

@+Maarten,

 



-- 
-----------------------------------------------------------------------
Objektfabrik Joachim Tuchel          [hidden email]
Fliederweg 1                         http://www.objektfabrik.de
D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

Maarten Mostert
In reply to this post by jtuchel

Hi Tom,

This is exactly what I do:

It happened again this afternoon, and what I noticed is that the cache for the SharedConfig was empty when it happened !

The sharedConfig is the first object I read aftern logging onto my database as it notably containes the descriptor version and the application's version. And in reply to other remarks, yes aSharedConfig is unique respects hash and identity and is allways old.


For the moment I conclude that if I have an existing Object which got emptied from the Cache Glorp will think it is new. This was not what I was expecting. For me register would deal with whatever new old updates etc.

 

This behaviour would however be in line with Joachims proposal to use privateRegisterAsOld: and confirms why I can register: 6000 times without problems while having an example in cache and get an exception when the cache is emptied, which is an essential difference.


Something else goes in this direction. Over the last year I modifed my application to basically read only 2 Objects. The model's root Object which spans about 20 tables and the SharedConfiguration which spans just one table. For everything else I drill down the proxies. By respecting unique identity == througout my application, Glorp will allways find something existing within its cache and not consider things to be new objects, and a  simple register: will do the job without hassle.

 

From my naif point of view however I should not need to use private methods and Glorp could/should use privateRegisterAsOld whenever it has exiting primary keys for an Object, and not bother me with primary key verifications.

 

For the moment I'll experiement with privateRegisterAsOld to see if that provides better consistancy.


Regards,

 

@+Maarten,

 

 

> "Tom Robinson" <[hidden email]> |

Maarten,

To update the single row in the database, I would do this:
  1. Read the file from the filesystem
  2. Read the row from the database
  3. Use the values in the file to update the object you read from the database
  4. Commit the transaction, which should cause an UPDATE

When I looked at the walkback you posted to Dropbox, I noticed that the duplicate key error is coming from an attempt to INSERT. This means that Glorp thinks this is a new object, not an existing one.

On 1/30/14, 5:45 PM, [hidden email] wrote:

Hi Kartsen and Joachim,

I use a unique Glorp session in my application of which getGlorpSession is the accessor method.

The SharedConfig Object is very simple object that doesn't hold any links to other objects and the table will allways contain one single row with id 1.

As it names said it holds some parameters that needs to be shared among other users like which day is a weekend day or how many hours a workday contains. In this particular case I am loading an MS Project file which agenda potentially modifies the SharedConfig object. The first time I load the file into my application all goes fine. If I load the file a second time shortly after it will hit the primary key error as nothing has been updated.

Lets notice that I've experienced primary key errors at many many occasions but it allways remained unpredictable as it often concerned other linked Objects and seemed vaguely related to the cache policy. It is the same problem I talked about to Nial and Tom during the last ESUG, but until now I never managed to reproduce it on a simple case.

 

Joachim you mention to use registerAsOld: honestly I never heard about that, are you meaning the private one ?

 

privateRegisterAsOld: anObject

"Register the object as something we already read from the database, skipping the isNew: test. Private! Normally you would just use register:"

| realObject |

currentUnitOfWork isNil ifTrue: [^self].

realObject := self realObjectFor: anObject ifNone: [^self].


 

currentUnitOfWork register: realObject

 

 

Obviously in this simple case I can easily work around the problem but I have hundreds of register: methods elsewhere in my application, so it would be good to know the intended policy here.

 

Regards,

 

Maarten,

 

classModelForSharedConfig: aClassModel


aClassModel newAttributeNamed: #id.

aClassModel newAttributeNamed: #current_version. "Float"

aClassModel newAttributeNamed: #descriptor_version.   "String"

aClassModel newAttributeNamed: #organisation_update type: Integer.

aClassModel newAttributeNamed: #hierarchy_update type: Integer.

aClassModel newAttributeNamed: #relations_update type: Integer.

aClassModel newAttributeNamed: #tablecreation type: Timestamp.

aClassModel newAttributeNamed: #weekendsunday type: Boolean.

aClassModel newAttributeNamed: #weekendmonday type: Boolean.

aClassModel newAttributeNamed: #weekendtuesday type: Boolean.

aClassModel newAttributeNamed: #weekendwednesday type: Boolean.

aClassModel newAttributeNamed: #weekendthursday type: Boolean.

aClassModel newAttributeNamed: #weekendfriday type: Boolean.

aClassModel newAttributeNamed: #weekendsaturday type: Boolean.

aClassModel newAttributeNamed: #secondsperday type: Integer

 

 

> "Joachim Tuchel" [hidden email] |

Hi again,

Re: the same primary key. Is this consisting of attributes of the object, or do you use sequences? In the first case, this is logical, the latter case would need a bit of digging into your code....

[hidden email] schrieb:

Hi,

It looks like Glorp really doesn't like to commit a registered object which basically has not been updated.

 

10 timesRepeat:

[self getGlorpSession inUnitOfWorkDo:

[self getGlorpSession register: aSharedConfig


"Do nothing really"]].

 

Whenever this happens it wants to create a new object with the same primary key.

Why ?

Regards,

@+Maarten,

 



_______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

jtuchel
Maarten,

if you really do exactly update an object during import, and this object has been read by the very same session in which you change its values, then something is completely broken. I doubt this is a Glorp issue then and you really need to dig deep into what happens to find the cause.

I remember strange things that I thought were bugs in Glorp and most often they were cause by myself and some stupid implementation of methods I should better not touch, like #= or #hash.

You say your sharedConfig is not found in the cache. Did you check if an instance of your sharedConfig class is in the cache and possibly just not found due to #= or #== problems? Did you check that it was there after reading it?

If you say you drill down proxies, do you actively do something there or do you just rely on Glorp's Proxy mechanism? I guess if you do something, try stopping that ;-)

Your description sounds weirder and weirder to me... ;-)

Joachim


Am 31.01.14 22:01, schrieb [hidden email]:

Hi Tom,

This is exactly what I do:

It happened again this afternoon, and what I noticed is that the cache for the SharedConfig was empty when it happened !

The sharedConfig is the first object I read aftern logging onto my database as it notably containes the descriptor version and the application's version. And in reply to other remarks, yes aSharedConfig is unique respects hash and identity and is allways old.


For the moment I conclude that if I have an existing Object which got emptied from the Cache Glorp will think it is new. This was not what I was expecting. For me register would deal with whatever new old updates etc.

 

This behaviour would however be in line with Joachims proposal to use privateRegisterAsOld: and confirms why I can register: 6000 times without problems while having an example in cache and get an exception when the cache is emptied, which is an essential difference.


Something else goes in this direction. Over the last year I modifed my application to basically read only 2 Objects. The model's root Object which spans about 20 tables and the SharedConfiguration which spans just one table. For everything else I drill down the proxies. By respecting unique identity == througout my application, Glorp will allways find something existing within its cache and not consider things to be new objects, and a  simple register: will do the job without hassle.

 

From my naif point of view however I should not need to use private methods and Glorp could/should use privateRegisterAsOld whenever it has exiting primary keys for an Object, and not bother me with primary key verifications.

 

For the moment I'll experiement with privateRegisterAsOld to see if that provides better consistancy.


Regards,

 

@+Maarten,

 

 

> "Tom Robinson" [hidden email] |

Maarten,

To update the single row in the database, I would do this:
  1. Read the file from the filesystem
  2. Read the row from the database
  3. Use the values in the file to update the object you read from the database
  4. Commit the transaction, which should cause an UPDATE

When I looked at the walkback you posted to Dropbox, I noticed that the duplicate key error is coming from an attempt to INSERT. This means that Glorp thinks this is a new object, not an existing one.

On 1/30/14, 5:45 PM, [hidden email] wrote:

Hi Kartsen and Joachim,

I use a unique Glorp session in my application of which getGlorpSession is the accessor method.

The SharedConfig Object is very simple object that doesn't hold any links to other objects and the table will allways contain one single row with id 1.

As it names said it holds some parameters that needs to be shared among other users like which day is a weekend day or how many hours a workday contains. In this particular case I am loading an MS Project file which agenda potentially modifies the SharedConfig object. The first time I load the file into my application all goes fine. If I load the file a second time shortly after it will hit the primary key error as nothing has been updated.

Lets notice that I've experienced primary key errors at many many occasions but it allways remained unpredictable as it often concerned other linked Objects and seemed vaguely related to the cache policy. It is the same problem I talked about to Nial and Tom during the last ESUG, but until now I never managed to reproduce it on a simple case.

 

Joachim you mention to use registerAsOld: honestly I never heard about that, are you meaning the private one ?

 

privateRegisterAsOld: anObject

"Register the object as something we already read from the database, skipping the isNew: test. Private! Normally you would just use register:"

| realObject |

currentUnitOfWork isNil ifTrue: [^self].

realObject := self realObjectFor: anObject ifNone: [^self].


 

currentUnitOfWork register: realObject

 

 

Obviously in this simple case I can easily work around the problem but I have hundreds of register: methods elsewhere in my application, so it would be good to know the intended policy here.

 

Regards,

 

Maarten,

 

classModelForSharedConfig: aClassModel


aClassModel newAttributeNamed: #id.

aClassModel newAttributeNamed: #current_version. "Float"

aClassModel newAttributeNamed: #descriptor_version.   "String"

aClassModel newAttributeNamed: #organisation_update type: Integer.

aClassModel newAttributeNamed: #hierarchy_update type: Integer.

aClassModel newAttributeNamed: #relations_update type: Integer.

aClassModel newAttributeNamed: #tablecreation type: Timestamp.

aClassModel newAttributeNamed: #weekendsunday type: Boolean.

aClassModel newAttributeNamed: #weekendmonday type: Boolean.

aClassModel newAttributeNamed: #weekendtuesday type: Boolean.

aClassModel newAttributeNamed: #weekendwednesday type: Boolean.

aClassModel newAttributeNamed: #weekendthursday type: Boolean.

aClassModel newAttributeNamed: #weekendfriday type: Boolean.

aClassModel newAttributeNamed: #weekendsaturday type: Boolean.

aClassModel newAttributeNamed: #secondsperday type: Integer

 

 

> "Joachim Tuchel" [hidden email] |

Hi again,

Re: the same primary key. Is this consisting of attributes of the object, or do you use sequences? In the first case, this is logical, the latter case would need a bit of digging into your code....

[hidden email] schrieb:

Hi,

It looks like Glorp really doesn't like to commit a registered object which basically has not been updated.

 

10 timesRepeat:

[self getGlorpSession inUnitOfWorkDo:

[self getGlorpSession register: aSharedConfig


"Do nothing really"]].

 

Whenever this happens it wants to create a new object with the same primary key.

Why ?

Regards,

@+Maarten,

 



_______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

jtuchel
In reply to this post by Maarten Mostert
Maarten,

one more idea: if you update that object. Do you change its attributes that are mapped as primary keys? What types are they mapped as?

Joachim


Am 31.01.14 22:01, schrieb [hidden email]:

Hi Tom,

This is exactly what I do:

It happened again this afternoon, and what I noticed is that the cache for the SharedConfig was empty when it happened !

The sharedConfig is the first object I read aftern logging onto my database as it notably containes the descriptor version and the application's version. And in reply to other remarks, yes aSharedConfig is unique respects hash and identity and is allways old.


For the moment I conclude that if I have an existing Object which got emptied from the Cache Glorp will think it is new. This was not what I was expecting. For me register would deal with whatever new old updates etc.

 

This behaviour would however be in line with Joachims proposal to use privateRegisterAsOld: and confirms why I can register: 6000 times without problems while having an example in cache and get an exception when the cache is emptied, which is an essential difference.


Something else goes in this direction. Over the last year I modifed my application to basically read only 2 Objects. The model's root Object which spans about 20 tables and the SharedConfiguration which spans just one table. For everything else I drill down the proxies. By respecting unique identity == througout my application, Glorp will allways find something existing within its cache and not consider things to be new objects, and a  simple register: will do the job without hassle.

 

From my naif point of view however I should not need to use private methods and Glorp could/should use privateRegisterAsOld whenever it has exiting primary keys for an Object, and not bother me with primary key verifications.

 

For the moment I'll experiement with privateRegisterAsOld to see if that provides better consistancy.


Regards,

 

@+Maarten,

 

 

> "Tom Robinson" [hidden email] |

Maarten,

To update the single row in the database, I would do this:
  1. Read the file from the filesystem
  2. Read the row from the database
  3. Use the values in the file to update the object you read from the database
  4. Commit the transaction, which should cause an UPDATE

When I looked at the walkback you posted to Dropbox, I noticed that the duplicate key error is coming from an attempt to INSERT. This means that Glorp thinks this is a new object, not an existing one.

On 1/30/14, 5:45 PM, [hidden email] wrote:

Hi Kartsen and Joachim,

I use a unique Glorp session in my application of which getGlorpSession is the accessor method.

The SharedConfig Object is very simple object that doesn't hold any links to other objects and the table will allways contain one single row with id 1.

As it names said it holds some parameters that needs to be shared among other users like which day is a weekend day or how many hours a workday contains. In this particular case I am loading an MS Project file which agenda potentially modifies the SharedConfig object. The first time I load the file into my application all goes fine. If I load the file a second time shortly after it will hit the primary key error as nothing has been updated.

Lets notice that I've experienced primary key errors at many many occasions but it allways remained unpredictable as it often concerned other linked Objects and seemed vaguely related to the cache policy. It is the same problem I talked about to Nial and Tom during the last ESUG, but until now I never managed to reproduce it on a simple case.

 

Joachim you mention to use registerAsOld: honestly I never heard about that, are you meaning the private one ?

 

privateRegisterAsOld: anObject

"Register the object as something we already read from the database, skipping the isNew: test. Private! Normally you would just use register:"

| realObject |

currentUnitOfWork isNil ifTrue: [^self].

realObject := self realObjectFor: anObject ifNone: [^self].


 

currentUnitOfWork register: realObject

 

 

Obviously in this simple case I can easily work around the problem but I have hundreds of register: methods elsewhere in my application, so it would be good to know the intended policy here.

 

Regards,

 

Maarten,

 

classModelForSharedConfig: aClassModel


aClassModel newAttributeNamed: #id.

aClassModel newAttributeNamed: #current_version. "Float"

aClassModel newAttributeNamed: #descriptor_version.   "String"

aClassModel newAttributeNamed: #organisation_update type: Integer.

aClassModel newAttributeNamed: #hierarchy_update type: Integer.

aClassModel newAttributeNamed: #relations_update type: Integer.

aClassModel newAttributeNamed: #tablecreation type: Timestamp.

aClassModel newAttributeNamed: #weekendsunday type: Boolean.

aClassModel newAttributeNamed: #weekendmonday type: Boolean.

aClassModel newAttributeNamed: #weekendtuesday type: Boolean.

aClassModel newAttributeNamed: #weekendwednesday type: Boolean.

aClassModel newAttributeNamed: #weekendthursday type: Boolean.

aClassModel newAttributeNamed: #weekendfriday type: Boolean.

aClassModel newAttributeNamed: #weekendsaturday type: Boolean.

aClassModel newAttributeNamed: #secondsperday type: Integer

 

 

> "Joachim Tuchel" [hidden email] |

Hi again,

Re: the same primary key. Is this consisting of attributes of the object, or do you use sequences? In the first case, this is logical, the latter case would need a bit of digging into your code....

[hidden email] schrieb:

Hi,

It looks like Glorp really doesn't like to commit a registered object which basically has not been updated.

 

10 timesRepeat:

[self getGlorpSession inUnitOfWorkDo:

[self getGlorpSession register: aSharedConfig


"Do nothing really"]].

 

Whenever this happens it wants to create a new object with the same primary key.

Why ?

Regards,

@+Maarten,

 



_______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

Maarten Mostert
In reply to this post by jtuchel

Dear Nial & Joachim,

 

> If you use #privateRegisterAsOld: to set the undoMap but do not populate
> the cache, any subsequent operation on that session that attempts to
> read the object will read a copy, not recognise the identity. You can
> then get two equal but non-identical objects in the undoMap. If you
> change one and not the other, you may see what you expect. If you
> change the one you added via #privateRegisterAsOld:, then (intentionally
> or in a closure) read the object again, then change the read object, now
> you have two no-longer-the-same objects in the undoMap, both comparing
> themselves to same-but-not-identical memento objects, both mapping to
> the same database key. I've not done this aned stepped through cases to
> see just what all can go wrong - but my instincts are dead against it!

 

The above is exactly what I mean and experience and I am happy you now understand what I mean.

A good example is also to send refresh to an Object. Of from there its easy to end up with a total mess as you have a model which has different proxy values for the same thing ! It'll drive you crazy. I tried for some time to refresh everything before sending an update, but that didn't help, as in many cases Glorp still managed to find identity differences far away from the object I actually tried to update and still trigger a primary key error.

 

>


> If you populate the cache instead, you can just register the object in
> the usual way as soon as you give the session a UnitOfWork. It will be
> put in the undoMap and changes will be tracked; no need to for any
> special call of #privateRegisterAsOld:.
>
> To populate the cache you must have the key as well as the value. You
> can get this from the cache of the session in which you previously read
> it or via the descriptor as in
> session
> cacheAt:
> (session descriptorFor: anObject)
> primaryKeyFor: anObject
> put: anObject

 

Oké, a solution would be to write a registerExisting: method that veryfies wheter the Object is in the cache and if not puts it in there and doing ordinary registration afterwards.

In this way perfect identity is maintained and we avoid to re-read the whole model or empty the cache by reseting the session.

This can be a solution in some cases but would not be my preferred one.

Normally Glorp seems to know when to update its cache based on its cache policy, and I think it should be that way. If I manage to maintain consistancy of identity within my image I should only need to tweak my cache policy to balance between minimised database traffic and raised out of sync problems.

 

Understanding how Glorp does its magic in refreshing its cache can help to make it failsafe. Currently I suspect Glorp to know how to update its cache up to a point where it manages to find perfect identity, and to be lost the moment its requested a value which is not connected with the rest of the model and no longer in cache, which is the case with my SharedConfig object.

 

The downside of my single object knows all other approach is that in order to keep perfect identity I'll need to request all the airplane tickets of a client to find the one who left from London, which is not very efficient.


> The effect of this is like
> anObject := session
> readOneOf: anObject class
> where: [:each | each = myObject]
> but of course it saves a database trip and it preserves the
> image-identity of anObject. Both put anObject in the cache of the
> session, able to be registered.
>
> If however the object obtained by the second statement would not be the
> same, save for image identity, as the object obtained by the first, then
> doing the first would put the session's cache in an incorrect state for
> that object. The implied scenario is
>
> - you read the object in a prior session
>
> - you are confident it has not changed in either the image or the
> database

>

> - you tell a fresh Glorp session to trust you and treat the object
> as if the new session had just read it from the database

 

I only work with one session, resetting it is the last resort, however I would love to know how to tell Glorp to mark something as Dirty so it triggers a refresh without disturbing the rest of the model.


>
> FYI I have not done exhaustive testing using Glorp to transfer objects
> between sessions in this way. I found this as a side effect of studying
> ways round the fact that deleting and reading an object in the same
> session could cause an error (rarely an issue, but someone met it), but

Good to know will keep it in mind.
> we've fixed that problem in 8.0 and a patch is available from support
> for earlier versions so I've not pursued it further. However I believe
> being able to move objects from one session to another could be a
> valuable if dangerous ability. (So I'd be pleased to hear of any
> problems or advantages met in doing this.)
>
> HTH
> Niall Ross
>

 

Thanks,

 

@+Maarten,

 

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.
Reply | Threaded
Open this post in threaded view
|

Re: [vwnc] Commitments without update

Maarten Mostert

Hi everyone,

I know experiment with the following registerExisting: method which walks nicely over my initial problem.

I have no idea yet however if I can reinsert an object someone else deleted from the database while keeping perfect identity in the image. If it proofs to work however it would be an elegant way.

Regards,

@+Maarten,

 

 

registerExisting: anObject

"Register an existing object which complies to full identity. First Check wheter the object exist on the database by counting, if it no longer exist set its primary key to nil and go directly to register.

If a single instance exist on the database check wheter its in cache, if not adds it to the cache to avoids any primarykey error. For the moment this method is limited to object with a single primary key but that can envolve easily"


| aCounter keyName |

(self descriptorFor: anObject) primaryTable primaryKeyFields size > 1

ifTrue: [self error: 'This object has multiple primary keys'].

aCounter := self count: anObject class

where:

[:each |

keyName := (self descriptorFor: anObject) primaryTable primaryKeyFields

first name.

(each perform: keyName asSymbol)

= ((self descriptorFor: anObject) primaryKeyFor: anObject)].

aCounter = 1

ifTrue:

[super halt.

((self cacheFor: anObject)

includesKey: ((self descriptorFor: anObject) primaryKeyFor: anObject)

withClass: anObject class)

ifFalse:

[MyDialog warn: 'Not in cache'.

(self cacheFor: anObject)

at: ((self descriptorFor: anObject) primaryKeyFor: anObject)

ifAbsentPut: [anObject]]]

ifFalse: [anObject perform: (keyName , ':') asSymbol with: nil].

^self register: anObject

 

 


 

> [hidden email] |

Dear Nial & Joachim,

 

> If you use #privateRegisterAsOld: to set the undoMap but do not populate
> the cache, any subsequent operation on that session that attempts to
> read the object will read a copy, not recognise the identity. You can
> then get two equal but non-identical objects in the undoMap. If you
> change one and not the other, you may see what you expect. If you
> change the one you added via #privateRegisterAsOld:, then (intentionally
> or in a closure) read the object again, then change the read object, now
> you have two no-longer-the-same objects in the undoMap, both comparing
> themselves to same-but-not-identical memento objects, both mapping to
> the same database key. I've not done this aned stepped through cases to
> see just what all can go wrong - but my instincts are dead against it!

 

The above is exactly what I mean and experience and I am happy you now understand what I mean.

A good example is also to send refresh to an Object. Of from there its easy to end up with a total mess as you have a model which has different proxy values for the same thing ! It'll drive you crazy. I tried for some time to refresh everything before sending an update, but that didn't help, as in many cases Glorp still managed to find identity differences far away from the object I actually tried to update and still trigger a primary key error.

 

>


> If you populate the cache instead, you can just register the object in
> the usual way as soon as you give the session a UnitOfWork. It will be
> put in the undoMap and changes will be tracked; no need to for any
> special call of #privateRegisterAsOld:.
>
> To populate the cache you must have the key as well as the value. You
> can get this from the cache of the session in which you previously read
> it or via the descriptor as in
> session
> cacheAt:
> (session descriptorFor: anObject)
> primaryKeyFor: anObject
> put: anObject

 

Oké, a solution would be to write a registerExisting: method that veryfies wheter the Object is in the cache and if not puts it in there and doing ordinary registration afterwards.

In this way perfect identity is maintained and we avoid to re-read the whole model or empty the cache by reseting the session.

This can be a solution in some cases but would not be my preferred one.

Normally Glorp seems to know when to update its cache based on its cache policy, and I think it should be that way. If I manage to maintain consistancy of identity within my image I should only need to tweak my cache policy to balance between minimised database traffic and raised out of sync problems.

 

Understanding how Glorp does its magic in refreshing its cache can help to make it failsafe. Currently I suspect Glorp to know how to update its cache up to a point where it manages to find perfect identity, and to be lost the moment its requested a value which is not connected with the rest of the model and no longer in cache, which is the case with my SharedConfig object.

 

The downside of my single object knows all other approach is that in order to keep perfect identity I'll need to request all the airplane tickets of a client to find the one who left from London, which is not very efficient.


> The effect of this is like
> anObject := session
> readOneOf: anObject class
> where: [:each | each = myObject]
> but of course it saves a database trip and it preserves the
> image-identity of anObject. Both put anObject in the cache of the
> session, able to be registered.
>
> If however the object obtained by the second statement would not be the
> same, save for image identity, as the object obtained by the first, then
> doing the first would put the session's cache in an incorrect state for
> that object. The implied scenario is
>
> - you read the object in a prior session
>
> - you are confident it has not changed in either the image or the
> database

>

> - you tell a fresh Glorp session to trust you and treat the object
> as if the new session had just read it from the database

 

I only work with one session, resetting it is the last resort, however I would love to know how to tell Glorp to mark something as Dirty so it triggers a refresh without disturbing the rest of the model.


>
> FYI I have not done exhaustive testing using Glorp to transfer objects
> between sessions in this way. I found this as a side effect of studying
> ways round the fact that deleting and reading an object in the same
> session could cause an error (rarely an issue, but someone met it), but

Good to know will keep it in mind.
> we've fixed that problem in 8.0 and a patch is available from support
> for earlier versions so I've not pursued it further. However I believe
> being able to move objects from one session to another could be a
> valuable if dangerous ability. (So I'd be pleased to hear of any
> problems or advantages met in doing this.)
>
> HTH
> Niall Ross
>

 

Thanks,

 

@+Maarten,

 

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.