The problem is that simply having an active buffer reference in any active code instance will prevent a db DISCONNECT() from running to completion.
If the db reference was dynamic, and the dynamic buffer was deleted before the DISCONNECT, then it might work.
In that case, you will need to tell your STATIC class that you are about to disconnect the DB in which case you call a method of the STATIC class to release the lock. You call another method to reacquire the lock after reconnecting to the DB. I would suggest wrapping the DB disconnect/connect process into another static class.
That won't work! As Cameron and myself have shown with the sample code is that it's not about record locks you can control with your code. It's about a schema lock because the static instance remains in memory.
A class with a static member is ALSO static class. The reference to the hInstance have to be released. That class you guys refer to as singleton is missing a method that releases the static member Instance. The static instance that is created will remain in the memory even if you delete all the instance of objects. In this case you must call a method to release "hInstance" then disconnect.
Camerons code has shown that this won't work.
This is happening because you have not released CustomerHelperSingleton. Remember that a class with a static member is also static class.
DELETE OBJECT CustomerHelperSingleton:Instance.
DELETE OBJECT CustomerHelperSingleton. /* I'm not sure if this is possible, but basically, there is an instance that is implicitly created behind the scene the first time you try to access Instance when you run CustomerHelperSingleton:Instance, you are in fact creating a second instance of CustomerHelperSingleton. It just so happen that the property Instance is shared */
DELETE OBJECT CustomerHelperSingleton.
Unknown Field or Variable name - CustomerHelperSingleton. (201)
I found this old thread after reading Tom Bascom's presentation slides about static classes:
We have been using the same approach for replacing shared variables with static properties.
However, now I started to wonder if we should use a singleton class instead. In OE 11.4 you can pass an object as a parameter between client and AppServer. Using singleton, we could send this singleton object to AppServer but the same can not be done with a static class. So, if we need to access the same common values both in AppServer and client, using a singleton pattern might be useful.
However, now I started to wonder if we should use a singleton class instead. In OE 11.4 you can pass an object as a parameter between client and AppServer. Using singleton, we could send this
singleton object to AppServer but the same can not be done with a static class. So, if we need to access the same common values both in AppServer and client, using a singleton pattern might be useful.
this post as spam/abuse.
Hi Peter, thanks for you reply. Yes, I was thinking of passing the singleton object itself. Do you see some obstacles in that?
Passing a singleton will give you a new instance on the client each time so there will only be one instance of it on the server (well one on each agent)... on the client you'll have a bunch of those unless you only ask for it once but I doubt singleton pattern will enforce only one instance on the client. This is only a creational pattern while when passing objects around those are serialized and de-serialized back, will be interesting to find out what progress is going to do though.
Simon L Prinsloo
It's technically possible, of course, but then (I think) you're moving into a place where you're treating the object as a value object (or data transfer object) rather than a singleton. A singleton in my mind is one isntance of an object that does some work. By definition, there is one per AVM (one on the client, one per agent on the server). As Marian says elsewhere, passing the singleton results in more than one singleton.
The pseudo-code below shows how I'd think about it. (there are some details that will vary). The point is to keep the singleton and data-transfer-object patterns distinct in your mind.
/* this is a singleton*/
/* this is ONE way of implementing a singleton; not my first choice,
but it's readable */
def static property Instance as UserContextManager get. private set.
method public UserContext GetCurrentContext().
method public void SetCurrentContext(poUC as UserContext).
/* other methods to do Stuf */
/*this is the data transfer object */
class UserContext serializable /* 11.4+ or roll-your-own */:
def pub property Name as char get. set.
def pub property SomeOtherData as class Foo get. set.
/* whatever you want to consider context */
method public void CallAppServer(<args>):
oUC = UserContextManager:GetCurrentContext().
run Server/ServiceInterface.p on hAppServer (
/* ServiceInterface.p */
def input parameter <args>
def input-output parameter poUC as UserContext.
/* run update_ledger.p or whatever needs running */
poUC = UserContextManager:GetCurrentContext().
Peter, thanks a lot for sharing your thoughts and sample code. That approach makes sense.
BTW, there seems to be a couple of typos in the sample code:
e.g. UserContextManager:GetCurrentContext(oUC) should be UserContextManager:SetCurrentContext(oUC).
but the idea if fully understandable.