User Name Password Register
DaniWeb IT Discussion Community
All
What is DaniWeb IT Discussion Community?
You're currently browsing the Pascal and Delphi section within the Software Development category of DaniWeb, a massive community of 391,782 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 3,540 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our Pascal and Delphi advertiser:
Views: 1195 | Replies: 12
Reply
Join Date: Mar 2008
Posts: 13
Reputation: MoZo1 is an unknown quantity at this point 
Rep Power: 0
Solved Threads: 0
MoZo1 MoZo1 is offline Offline
Newbie Poster

OnCalcField modifying its own DataSet - Error

  #1  
May 6th, 2008
Well... I could copy the data, and use that, but that would be very slow, and I would have to copy often and a lot. I have a table where records depends on another one. Still, it will be the backup if I can't solve this.
So every time I try to move the active record from inside the OnCalcField event I get a lot of some veird EOleException invalid argument error, even when I don't even read or write any data. I know, I must restore the dataset at the end of the event, as I do every time before EnableControls.

This is my event:
  1. procedure TForm1.calc(DataSet: TDataSet);
  2. begin
  3. try
  4. Dataset.FieldByName('Calc').AsInteger:=10;
  5. if qwe then exit;
  6. qwe:=true;
  7. dataset.DisableControls;
  8. //dataset.next;
  9. //if not dataset.Eof then dataset.prior;
  10. dataset.EnableControls;
  11. ListBox1.AddItem(Dataset.FieldByName('SampleNum').AsString,nil);
  12. qwe:=false;
  13. except
  14. showmessage('This never shows!');
  15. ADOQuery1.OnCalcFields:=nil;
  16. end;
  17. end;
When I try to uncomment the 2 lines it throws the errors, but I can't even catch it. If something handles the error, it couldn't become recursive because qwe prevents it. And I've already tryed with GotoBookmark and First, in case eof would cause this, but it's the same.

Also I can't find anything on google, so it would be nice if somebody could only show me a working example.
Thanks!
AddThis Social Bookmark Button
Reply With Quote  
Join Date: Nov 2007
Posts: 22
Reputation: ecostas is an unknown quantity at this point 
Rep Power: 1
Solved Threads: 0
ecostas ecostas is offline Offline
Newbie Poster

Re: OnCalcField modifying its own DataSet - Error

  #2  
May 6th, 2008
Hi. If you are using ClientDatasets, maybe you can try RecNo and Recordcount to find out if you are in the last record. But from your code I can' t understand why you need it. Maybe that's not exactly your code. Haven't tried my solution, to be honest.

Eduardo

Originally Posted by MoZo1 View Post
Well... I could copy the data, and use that, but that would be very slow, and I would have to copy often and a lot. I have a table where records depends on another one. Still, it will be the backup if I can't solve this.
So every time I try to move the active record from inside the OnCalcField event I get a lot of some veird EOleException invalid argument error, even when I don't even read or write any data. I know, I must restore the dataset at the end of the event, as I do every time before EnableControls.

This is my event:
  1. procedure TForm1.calc(DataSet: TDataSet);
  2. begin
  3. try
  4. Dataset.FieldByName('Calc').AsInteger:=10;
  5. if qwe then exit;
  6. qwe:=true;
  7. dataset.DisableControls;
  8. //dataset.next;
  9. //if not dataset.Eof then dataset.prior;
  10. dataset.EnableControls;
  11. ListBox1.AddItem(Dataset.FieldByName('SampleNum').AsString,nil);
  12. qwe:=false;
  13. except
  14. showmessage('This never shows!');
  15. ADOQuery1.OnCalcFields:=nil;
  16. end;
  17. end;
When I try to uncomment the 2 lines it throws the errors, but I can't even catch it. If something handles the error, it couldn't become recursive because qwe prevents it. And I've already tryed with GotoBookmark and First, in case eof would cause this, but it's the same.

Also I can't find anything on google, so it would be nice if somebody could only show me a working example.
Thanks!
Reply With Quote  
Join Date: Mar 2008
Posts: 13
Reputation: MoZo1 is an unknown quantity at this point 
Rep Power: 0
Solved Threads: 0
MoZo1 MoZo1 is offline Offline
Newbie Poster

Re: OnCalcField modifying its own DataSet - Error

  #3  
May 7th, 2008
This code obviously doesn't need it, but I will in the program I'm writing. I've just made a test program to separate the error with the minimal code needed to reproduce it.
Of course in the final code there will be some procesing, but I'm happy that I haven't written 100 lines of code in a much more complicated program to debug this stupid error there.
And I've already written that I've tryed bookmark+first to eliminate this, but probably it's not this. Also I've tryed now [icode=delphi]if dataset.recno>dataset.recordcount-3 then exit;[/icode] after the 1st line with the exit, everything is the same. But I don't even reach the end of the dataset, because the dbgrid is too small to draw it (I know this by the logging line), so it really can't be this.

Also a new thing I've noticed that if I make a breakpoint then I see that this code runs for some time without error, and then never runs when the errors come.
Reply With Quote  
Join Date: Jun 2006
Location: Blumenau, Brazil
Posts: 67
Reputation: Micheus is an unknown quantity at this point 
Rep Power: 3
Solved Threads: 4
Micheus's Avatar
Micheus Micheus is offline Offline
Junior Poster in Training

Re: OnCalcField modifying its own DataSet - Error

  #4  
May 7th, 2008
Originally Posted by MoZo1 View Post
So every time I try to move the active record from inside the OnCalcField event I get a lot of some veird EOleException invalid argument error, even when I don't even read or write any data.
Does you have looked in the help file and search for OnCalcFields event?

MoZo1, this event occurs in many circumstances and many times. See this small portion:
OnCalcFields is called frequently, so the code it contains should be brief.
When the AutoCalcFields property is True, OnCalcFields is triggered when:

• A dataset is opened.
• A dataset is put into dsEdit state.
• Focus moves from one visual control to another, or from one column to another is a data-aware grid control and modifications were made to the record.
• A record is retrieved from a database.


So, from the moment that dataset is opened until all data is showed in the DBGrid, your application will notice that OnCalcEvent was triggered a lote of times.
You can have an idea from this by putting one TMemo (Memo1) into your form and adding this code to your OnCalcFields event:
  1. procedure TForm1.calc(DataSet: TDataSet);
  2. begin
  3. Memo1.Lines.Add('OnCalcFields passed...');
  4. end;
You never must change any data field from dataset owned by calculated field (except from the calculated fields), as well dataset position at this event (it will generate recursive calls).

If You need to make some thing when a DBGrid selection is changed (current record has its position changed), You must use the OnDataChange evento from TDataDouce componente connected to desired dataset.

Bye
"It always has, at least, two ways to make one same thing. Exactly that they are certain and wrong"(Micheus)

Brazil - Blumenau
Reply With Quote  
Join Date: Mar 2008
Posts: 13
Reputation: MoZo1 is an unknown quantity at this point 
Rep Power: 0
Solved Threads: 0
MoZo1 MoZo1 is offline Offline
Newbie Poster

Re: OnCalcField modifying its own DataSet - Error

  #5  
May 7th, 2008
As you can see, I already have a logging code. My event is called every time something read a calculated field. So at the start of the program, when the dbgrid reads whatever it displays, and when I scroll it later, then for only those records.
And I know, that I shouldn't do this, but I'm handling recursive calls, and I'm returning the cursor where it was, so I should be able to do this.
And now the case is that this table has a "foregin key" that points into the same table, so I have to access those records, and I have to make calculated fields from them. To be worse, I have to show the effect when the user changes one value instantly, so this is why I use calculated fields.
Anybody that knows how to fix this, or can link here some webpage about this topic would be appreciated. Thanks!
Reply With Quote  
Join Date: Jun 2006
Location: Blumenau, Brazil
Posts: 67
Reputation: Micheus is an unknown quantity at this point 
Rep Power: 3
Solved Threads: 4
Micheus's Avatar
Micheus Micheus is offline Offline
Junior Poster in Training

Re: OnCalcField modifying its own DataSet - Error

  #6  
May 7th, 2008
Originally Posted by MoZo1 View Post
My event is called every time something read a calculated field.
when you must to initilize it.

... but I'm handling recursive calls, and I'm returning the cursor where it was, so I should be able to do this.
You can't.
DisableControls only will "stops" to update any data-aware control connected to this dataset. Moving across dataset will trigger this evento in order to update the calculated fields for this new row (cursor position).

And now the case is that this table has a "foregin key" that points into the same table, so I have to access those records, and I have to make calculated fields from them. To be worse, I have to show the effect when the user changes one value instantly, so this is why I use calculated fields.
In this case, You must use an other dataset only to reach this goal. I sugest that You use some query componente to do this.

Did you understood? If You explain better, putting table fields and relationships, maybe I could examplify.

Bye
"It always has, at least, two ways to make one same thing. Exactly that they are certain and wrong"(Micheus)

Brazil - Blumenau
Reply With Quote  
Join Date: Mar 2008
Posts: 13
Reputation: MoZo1 is an unknown quantity at this point 
Rep Power: 0
Solved Threads: 0
MoZo1 MoZo1 is offline Offline
Newbie Poster

Re: OnCalcField modifying its own DataSet - Error

  #7  
May 11th, 2008
Originally Posted by Micheus View Post
when you must to initilize it.

I must initialize it every time something reads it, because delphi doesn't store them, and TADOQuery can't use internally calculated fields. But this doesn't really matter, because if it can run once, it could run any times.
Originally Posted by Micheus View Post
You can't.
DisableControls only will "stops" to update any data-aware control connected to this dataset. Moving across dataset will trigger this evento in order to update the calculated fields for this new row (cursor position).
So with other words, only outside calls will need that data, but when the data is being calculated, the object (that will use this database) will turn off the calculation internally, because every call that occurs there are from inside (of course, because delphi is strictly single threaded), so it won't use that data ever, so other calculation requests won't cause recursions, but instantly returns with nothing instead.
But that second calculate call won't trigger another one, so it stops. DisableControls only helps that these null values won't be cached into the visual controls. I've successfully used this technic once, the only difference was that it was a phisycally stored field.
Originally Posted by Micheus View Post
In this case, You must use an other dataset only to reach this goal. I sugest that You use some query componente to do this.

And refresh it with all of the records every time the other one get changed. If it can't be helped, I'll do this of course, but I still don't know what is this exeption, and why is it there.
Originally Posted by Micheus View Post
Did you understood? If You explain better, putting table fields and relationships, maybe I could examplify.

Bye

I know what I'm doing. I don't know what the hell Delphi is doing. T_T
Of course I could solve this with the second table, or a memory cache, or whatever easily, but this sollution would be the easyest and fastest, and I don't see any obstacle in theory why I can't do this. Well, at least I've tryed... Thanks for the help anyway!
Reply With Quote  
Join Date: Aug 2007
Location: Gunnison, Colorado
Posts: 54
Reputation: fishsqzr is an unknown quantity at this point 
Rep Power: 2
Solved Threads: 1
fishsqzr fishsqzr is offline Offline
Junior Poster in Training

Re: OnCalcField modifying its own DataSet - Error

  #8  
May 11th, 2008
I haven't tried to run your code, but I can tell you this:
When your uncomment the line which moves to the next record, what is happening is that Delphi is calling OnCalc again automatically as soon as the record changes, and you are probably trashing the stack when the call goes into an endless loop because each call to OnCalc moves the record which send it back to OnCalc.......... OnCalc is best used to just update the current record (or other data dependent on the current record). It is a very useful tool (I sure with C#.NET had it) but it can't be used for everything.

I'm not quite sure what it is you're actually trying to accomplish but it looks like you are using the wrong event.
Reply With Quote  
Join Date: Mar 2008
Posts: 13
Reputation: MoZo1 is an unknown quantity at this point 
Rep Power: 0
Solved Threads: 0
MoZo1 MoZo1 is offline Offline
Newbie Poster

Re: OnCalcField modifying its own DataSet - Error

  #9  
May 12th, 2008
Well, I'm going to forfeit this one, but please notice these:

Also a new thing I've noticed that if I make a breakpoint then I see that this code runs for some time without error, and then never runs when the errors come.
-> No recursion occurs on my level of code. And I've already told that the error is an EOleException and not a stack overflow.

And again this one too: Watch qwe! When my event is triggered, then it sets the qwe variable (disabling itself), then disablecontrols, and after then it moves the dataset, retriggers itself, but won't do anything while qwe is true, because it knows that calculating isn't needed, and when it've finished with the processing, it unsets qwe (enabling itself), enablecontrols and returns the value. The visual controls won't notice a thing because of disablecontrols, and the recursive calling on the dataset is handled.

And at last, no stack overflow error, no damn long stack, and no recursion can be detected through breakpoints. Probably if you haven't tryed my code, you will think, this isn't something strange, and I've just failed to notice a stack overflow, and writing stupidity here. But even then, you should be able to point out what's wrong with my handling.
And if you're interested, I use delphi 2005!
Last edited by MoZo1 : May 12th, 2008 at 2:20 am.
Reply With Quote  
Join Date: Jun 2006
Location: Blumenau, Brazil
Posts: 67
Reputation: Micheus is an unknown quantity at this point 
Rep Power: 3
Solved Threads: 4
Micheus's Avatar
Micheus Micheus is offline Offline
Junior Poster in Training

Re: OnCalcField modifying its own DataSet - Error

  #10  
May 13th, 2008
Originally Posted by MoZo1 View Post
And refresh it with all of the records every time the other one get changed.
Not all. Only use a query component with restricted SQL instruction - use WHERE clause in order to get only the respective record at once - and in SELECT clause, use only the necessary fields (not all, like "select * from...").

Originally Posted by MoZo1 View Post
And again this one too: Watch qwe! When my event is triggered, then it sets the qwe variable (disabling itself), then disablecontrols, and after then it moves the dataset, retriggers itself, but won't do anything while qwe is true, because it knows that calculating isn't needed, and when it've finished with the processing, it unsets qwe (enabling itself), enablecontrols and returns the value. The visual controls won't notice a thing because of disablecontrols, and the recursive calling on the dataset is handled.
It's not totally truth.
Just make this change in your code:
  1. ...
  2. Dataset.FieldByName('Calc').AsInteger:=10;
  3. if qwe then
  4. begin
  5. ListBox1.AddItem('OnCalcField event recalled',nil);
  6. exit;
  7. end;
  8. qwe:=true;
  9. ...

And at last, no stack overflow error, no damn long stack, and no recursion can be detected through breakpoints.
It's truth!

Is very difficult to debug this kind of code, because a break point at this event will unfortunately make the DBGrid paint its self. And in order to get data to display...

Take a look at the attached image. I have positioned the delphi windows in order to prevente redrawing influence.
The DBGrid's linked dataset has seven records where PersonCode has a sequencial value from 1 to 7. Notice this points:
- Call Stack window shows what is in process where the error occurs;
- Editor windows shows the break point at line where the error occurs - DBGrid unit. See tooltip window appoints the EOleException;
- At background, Form1 is the program running. Looking at the DBGrid we can ask: Where is displayed values when PersonCode is 2? And looking to ListBox we see that a recursive call was made when trying process this value.

You can try by your self.

Originally Posted by MoZo1 View Post
I know what I'm doing. I don't know what the hell Delphi is doing. T_T
..., and I don't see any obstacle in theory why I can't do this.
Well, if You really need to know what the hell Delphi is doing, I think that now You have a track to go ahead.

My final words is: Do not use OnCalcFields event by this way.


Good luck.
Attached Images
File Type: jpg OLE_Error.jpg (98.4 KB, 3 views)
"It always has, at least, two ways to make one same thing. Exactly that they are certain and wrong"(Micheus)

Brazil - Blumenau
Reply With Quote  
Reply

Only community members can participate in forum threads. You must register or log in to contribute.

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)

 

DaniWeb Pascal and Delphi Marketplace
Thread Tools Display Modes

Other Threads in the Pascal and Delphi Forum

All times are GMT -4. The time now is 4:58 am.
Forum system based on vBulletin Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
©2003 - 2008 DaniWeb® LLC