using a vc++ gui to interact with an MSAccess db. uisng try/catch
blocks to catch exceptions like inserting duplicate yr,mo,day combos
into the table.
the db squawks but the bogus record is entered into the db, thus requiring,
manual deletion.
attempts to set a flag that is tripped should the catch block be called
and the go back to delete the record also fail since the
db wont allow operations on the bad record that i am trying to
prevent getting in in the first place.
how can i prevent records with detectable errors from getting in?
using ADO.
thanks in advance.
j
DanielaTm
March 21st, 2007, 07:42 AM
Why don't you create an unique index on database? it certainly prevents duplicate keys
jim enright
March 21st, 2007, 10:38 AM
the table is indexed no dupes by yr,mo,day. the problem is that when i programattically attempt to add a new record with the same
yr, mo, day Access supplants the day with 0 and adds a record known by
Access to be incorrect.
additionally, i kknow beforehand from the try/catch block that the
Access table knows this is record violates the table rules but then
changes my data so it can insert the record. This is whacked.
if the record violates the rules it should not be entered and Access should
not be making any attempts to change data and enter it.
my attempts to programaticaly undo the damage after the fact are then
frustrated by MSAccess saying it will not allow any operations (ie delete)
on a record that violates the rules.
i need a methodology to prevent the record getting in in the first place.
thanks - j
TheCPUWizard
March 21st, 2007, 10:47 AM
This should NOT be happening.
1) Can you post a minimal yet complete sample that illustrates this issue?
2) What versions of VC and Access are you using? Have you applied all appropriate updates?
davide++
March 21st, 2007, 12:31 PM
Hi all.
If you add an unique index on table (as Daniela said) Access won't be able to insert a record with same value, and will throw an exception that you can manage in try/catch block.
Another simple way is execute a SELECT COUNT(*) query to check if record exists in table before to perform INSERT command: in this case you won't execute the INSERT.
jim enright
March 21st, 2007, 12:43 PM
thanks for the repsonses - will try to replicate problem outside of app.
trying like hell to avoid running an sql prequery simply because
the point is that the try/catch clocks should be able to detect and correct.
talk to you in a bit.
thanks - j
TheCPUWizard
March 21st, 2007, 01:41 PM
Another simple way is execute a SELECT COUNT(*) query to check if record exists in table before to perform INSERT command: in this case you won't execute the INSERT.
But will totally fall apart in a multi user scenario (which should almost always be designed for), unless you start using transactions (which are not "really" supported by Access, and even in that case will incude significant overhead.
Much better to debug the existing problem than to try to hide it....
davide++
March 22nd, 2007, 07:25 AM
But will totally fall apart in a multi user scenario (which should almost always be designed for), unless you start using transactions (which are not "really" supported by Access, and even in that case will incude significant overhead.
Much better to debug the existing problem than to try to hide it....
Hi all
You don't hide a problem using COUNT(*), simply check if there's an inconsistent situation and avoid it.
An alternative (and valid) way is using the exception mechanism, but I think both techiques have good points and bad points.
In my opinion query makes code more readable, because one can do control and action "in the same place": using exception, one "breaks" control and action in two points in the code. Well, this is a simple situation, and when INSERT fails probably one wants show an error message and stop process; but in more complex cases one would perform other operations on db (for example, to log the error into another table), and what happens if these operations fail? One must manage the exception within an exception...
Exceptions are very useful - are the best thing - to catch and manage unexpected errors (of course, they're very rare using Access).
TheCPUWizard
March 22nd, 2007, 07:46 AM
You don't hide a problem using COUNT(*), simply check if there's an inconsistent situation and avoid it.
The problem is that if you do the COUNT(*) before attempting the insert, then two people can still overlap, and you will end up with duplicate data (although it will be rarer, which is why I refer to it as hiding the problem, it may be weeks or months before it occurs.
If you do the COUNT(*) after then the data it still corrupt, and there is no repair (according to the OP).
IIRC, there was a bug of this nature in older versions of Access, and a HotFix was published. This should have been fixed in current versions. (I still have not seen what version is in use....).
davide++
March 22nd, 2007, 09:45 AM
The problem is that if you do the COUNT(*) before attempting the insert, then two people can still overlap, and you will end up with duplicate data (although it will be rarer, which is why I refer to it as hiding the problem, it may be weeks or months before it occurs.
If you do the COUNT(*) after then the data it still corrupt, and there is no repair (according to the OP).
IIRC, there was a bug of this nature in older versions of Access, and a HotFix was published. This should have been fixed in current versions. (I still have not seen what version is in use....).
Well.
Obviusoly perform the query after INSERT insn't very usefull... it's definitely unnecessary.
OK, it's true, but you won't solve this problem using exception instead of SELECT COUNT(*): in both cases the first wins and the second crashes. As you said, this situation is rarely, extremely rarely in my opinion if the two operations will executed in sequence (this isn't true for very complex systems, with hundred of user), so in general I can consider this type of error as an unexpected error, and manage it with exceptions: the important thing is that the unique index must be defined, because it assures database integrity, in any case.
I didn't say that exceptions are unnecessary, they should be always defined in good code.
The safiest way to avoid this problem is to generate the keys automatically, using specific database objects, such as auto-incremented fields or sequences.
jim enright
March 22nd, 2007, 02:35 PM
i have isolated and replicated the problem in a new Dialog based app named TestAccess
i have modified the TestAccessDlg.h file as follows:
return TRUE; // return TRUE unless you set the focus to a control
the problem is replicated in that there is a single record in the table
tos start with ratey = 2007, ratem = 3, rated = 22.
exceptions are thrown from the update function the starting from
where the attempt is made to set rated to 22. all fields thereafter
are set to 0. but the record is added with rated changed to 0.
if i attempt to manually attempt to cut and paste the single original
record, Access will not allow me to do anything. if i close the table
it will force the deletion of the record.
appreciate any insight - i need access to behave as if i were interactively using it. it should not change data i am attempting to insert.
thanks - j
TheCPUWizard
March 22nd, 2007, 02:38 PM
Can you do a "Clean" on the project directory (get rid of .obj,.exe,.sbr, etc) and zip up the results??? Also zip and post the mdb file (a small one)
Also I still have note seen the versions (but I might have missed a post).
jim enright
March 22nd, 2007, 03:08 PM
my bad - using vc++2005 and MSAccess 2003.
not sure i can zip anything but the .h and .cpp files for
the diagnostic app are very small - not much more than what
i posted.
will copy the access db and strip out all tables except postal
rate that would be very small also.
how would i attach these?
thanks - j
TheCPUWizard
March 22nd, 2007, 03:13 PM
Go down below the Reply to Thread box to Additional Options, there is an area for "Manage Attachments"
Just having the project/solution files etc will save some time in setting up the repro.... (trying to help as many people as possible...)
jim enright
March 22nd, 2007, 03:48 PM
attached the AccessTestDlg.h and .cpp files - the single table, single record
access db somehow takes up 192K > 100K limit.
will get a hold of some zip utility and get that loaded.
thanks for your help. let me know if there are other c++ files you need.
j
TheCPUWizard
March 22nd, 2007, 03:52 PM
Either that or e-mail it to me:
dvcorbin "at" optonline "dot" net
I will take a look at it later tonight, getting ready to go out to dinner and a show.....
jim enright
March 22nd, 2007, 04:48 PM
okay have zipped both the project (misppelled as procect.zip) and the access db (MSAccess.zip).
there is an AccessDBManager.cpp file that is in there but not needed
hope this helps
jim enright
March 23rd, 2007, 04:03 PM
MS had a great suggestion - give them $245 dollars and hope they
agree its a bug and so they will give it back.
on a more serious note, installing a validation rule on RateD to
be > 0 prevents the inclusion of an erroneous record but
the designation of y,m,d as a unique key ought to be sufficient.
if its sufficient in interactive mode it has to be sufficient for
transactional purposes.
jim enright
April 5th, 2007, 10:02 AM
still looking for answer to this and more general problem stated below:
using vc++2005/ADO and msaccess 2003.
whenver i attempt to move data from a GUI and add a new record to a table
i use a try/catch block. i found this to be excellent in getting explanations
back from msaccess as to why a candidate record will not be allowed in: eg:
duplicate keys, wrong data type, violation of table rules, etc.
the problem is that attempts to correct the candidate record fail. my
uninformed guess is that the following takes place:
access handles the first attempt to add a new record by placing the
info in an edit buffer, runs its integrity checks, and squawks if there are
problems - but does not remove the record from the edit buffer.
further attempts are frustrated because they are viewed by msaccess
as attempts to do other things without rectifying the first problem - the bad data in the edit buffer.
is there a way to remove the edit buffer record? if so i could use the
the try/catch block to undo the attempted load and then
attempt new data.
thanks - j
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.