Posts Tagged ‘ado’

How to write an infinite recursion … elegantly

Wednesday, February 2nd, 2011

I’m working on a DB Lookup Combo with filter, sorting and most important: instance search (like winamp).

So, I figured I’d use a TClientDataSet as a proxy dataset for my combo and just descend from TDBLookupComboBox

All nice and dandy until the part where I have to respond to changes in the original dataset and update my proxy one. As always I did it like


dataset.disableControls;

try

dataset.first;

while not dataset.eof do blabla

finally

datasert.enableControls;

end;

The component was integrated into a financial application and for some reason I got the freeze, but only for a few seconds. For the life of me I couldn’t figure out what it was wrong, especially because from about 10 similar adotables and about the same number of forms, similar in construction and components, it only happened with one and only one. MadExcept by itself was not useful as setting the freeze timeout to 2 second it didn’t fire. Then I remembered madTraceProcess.exe and that did it: it showed the issue being in my component. A few breakpoints in the right spot (trial and error) got me seeing the recursion happening on the dataset.enableControls line. A few more minutes of debugging proved that the issue was caused by that usage as I was doing it in the DataLink.DataSetChanged method which is called when the dataset “changes”. But if you look through the code in DB.pas you’ll notice that the datasetChanged is called in a lot more other situations, but most notably in EnableControls.

Long story short, this is probably the “best” infinite recursion I’ve ever seen till now. and it was caused because my assumption that datasetChanged is called when the dataset changes. Wrong, it is called in EnableControls as well.

Related posts

Row cannot be located for updating. Some values may have been changed since it was last read.

Thursday, January 13th, 2011

Yet another one of those cryptic messages that basically says “you’re screwed”.

So what was I doing this time? Well, I had my mysql tables designed as having different fields as float. It just came natural to me that way. Everything went well until today when I had to modify that field on a record which had some fractional part (until now I did modifications but only to values with no fractional part) and boom. Took me a while to figure it out that it was the float type of the mysql table field that caused this because you see, float in mysql at least is not exact. It’s an approximation. That means that ADO will have a hard time to find hte modified record if you modify the value with a fractional part. It will actually raise ”

Row cannot be located for updating. Some values may have been changed since it was last read.”

Happy me. Solution? Just change the mysql column float into decimal(M,L). I use Decimal(15,2) as it works fine for my application. Yeah, have a laugh at all those people suggesting cursor type changes, ado property modifications and so on. People, first find THE CAUSE, and then find a way to fix it.

Related posts

Multiple Step Operation Generated Errors – Check each status value

Wednesday, January 12th, 2011

Yet another cryptic error with an unusual/weird test case and solution.

So, my setup:

– a table with a date field marked null/not null (tried both, same thing)

– an TADOTable to work with the above

– added all fields in the field editor

– a TDBDateEdit from RXLib with DefaultToday set to true

You make an append. You don’t touch the date as it’s set for today. You change everything else. You post. And you get the error:

“Multiple Step Operation Generated Errors – Check each status value”

Why? Well, thing is that when you make the append, the underlying TDataSet will set the state of itself to dsInsert, at which point TDBDateEdit will notice that a new record is added and set the date to today which makes the date field to be added to the internal modified field list of the TCustomADODataSet.

Now, the code runs further and calls DoOnNewRecord which clears the above mentioned internal modified field list and hence, when you do post, the date field is not in the list and hence it is not posted.

Now, since on the client side the field is set and has a value, on DB side the field was not sent and is either null or lots of zeros (if field is set not null) and hence they do not match (in this latter case delphi will also error because it cannot convert it to date. Not sure when this is done, but it is done). So, ADO will now raise this error BUT, the record was already added, just with an invalid date value. And if you are in the not null scenario and reload the grid, you will surely get the “ Data provider or other service returned an E_FAIL status.

There you go, yet another scenario for that cryptic error message πŸ™‚

Related posts

Data provider or other service returned an E_FAIL status.

Monday, January 10th, 2011

It just happened. Took me a few minutes to track it down. I’ll be short:

– my steup: mysql and delphi with ADO. a table with a date field set to not null

– on client side, I inserted a record and for some reason did not set the date. that went as lots of zero-s in mysql.

now, when loading that record, I get that message because lots of zeros are not a valid date value.

There you go, another explanation for the dreaded message.

Related posts

Delphi, ADO: update/modify and delete from a join recordset

Monday, August 10th, 2009

It’s been a while since I’ve written a Db-app from scratch and a few days ago I started writing an invoice-like app for myself.
At one point I needed to insert/update/delete into/from a resultset of a join. I was getting this error:
“Row cannot be located for updating. Some values may have been changed since it was last read.”
After googleing for a little while I found the following golden piece of information on ADO programming on the web archive which was posted here

Now everything works like a charm πŸ™‚

Related posts