Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Programming Bulletproof Error 10262

859 views
Skip to first unread message

Mary L

unread,
Aug 3, 2010, 1:22:03 PM8/3/10
to
I'm creating a screen to access a new table I'm adding to the project
controller. For business reasons, we need a different kind of budget
tracking than what comes out of the box. (Actually I'm adding two tables - a
header and detail table - but I haven't gotten to the detail yet.) The
header table has two primary keys (and it could be argued that it only needs
one, and if it solves the problem I can go there) one for the project and one
for the document number - since each project will have new budgets created
almost every year. When I try to add a record (to an empty table) I get the
following error: Programming Bulletproof Error 10262 Invalid cursor value
passed to sinsert8(). Please make sure cursor value is greater than 0. Also
verify that this cursor has been passed to sql(). I've tried to put all
sorts of breakpoints before and during sinsert1(), sinsert4(), and sinsert8()
in the Solomon.VBTools.vb and none of them are tripping.

This is what I've got so far:
++Form1.vb:

Option Explicit On
Option Strict Off
Friend Class Form1
Inherits System.Windows.Forms.Form

Protected m_IsInitializing As Boolean
Protected ReadOnly Property IsInitializing() As Boolean
Get
Return m_IsInitializing
End Get
End Property

Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal
eventArgs As System.EventArgs) Handles MyBase.Load

Call ApplInit()
Call SetAddr(LEVEL0, "bxCostHeader", bxCostHeader, nxCostHeader)
Call SqlCursorEx(CSR_xCostHeader, LEVEL0, "CSR_xCostHeader",
"xCostHeader", "xCostHeader")
Call ScreenInit()
End Sub

Private Sub Form1_FormClosed(ByVal eventSender As System.Object, ByVal
eventArgs As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed


Call ScreenExit("", "")

End Sub

Private Sub cDocnbr_ChkEvent(ByRef ChkStrg As String, ByRef RetVal As
Short) Handles cDocnbr.ChkEvent
RetVal = PVChkFetch1(cBuilding, CSR_xCostHeader, ChkStrg,
bxCostHeader)
End Sub
End Class

++The SQL that creates the table and related procedure:

if exists (select * from sysobjects where id = object_id('dbo.xCostHeader')
and sysstat & 0xf = 3)
DROP TABLE xCostHeader
Go
Print 'Creating table: xCostHeader'
Go

Create Table xCostHeader (
BranchOverhead float not null,
ChemSupplies float not null,
Description char (60) not null,
docnbr char (10) not null,
effectDate smalldatetime not null,
effectDateEnd smalldatetime not null,
Equipment float not null,
Holidays float not null,
lupd_datetime smalldatetime not null,
lupd_prog char (8) not null,
lupd_user char (10) not null,
MgmtHW float not null,
NoteId int not null,
OthConsum float not null,
OthIndirect float not null,
OthPTO float not null,
PayrollIns float not null,
PeriodicHrs float not null,
PeriodicRate float not null,
preparedBy char (16) not null,
project char (16) not null,
SickDays float not null,
sqFtClean int not null,
sqFtTotal int not null,
Subcontractor float not null,
Supervision float not null,
Taxes float not null,
Transportation float not null,
UnHWFTHours float not null,
UnHWFTRate float not null,
UnHWPTHours float not null,
UnHWPTRate float not null,
Uniforms float not null,
UnPenHours float not null,
UnPenRate float not null,
user0 smalldatetime not null,
user1 char (30) not null,
user2 char (30) not null,
user3 char (30) not null,
user4 float not null,
user5 float not null,
user6 float not null,
Vacation float not null,
tstamp Timestamp,
constraint xCostHeader0 primary key (project, docnbr))
Go
Print 'Creating procedure: xCostHeader_p0'
go
create proc xCostHeader_p0
@parm1 varchar(16),
@parm2 varchar(10)
as
select * from xCostHeader
where project = @parm1
and docnbr like @parm2
order by project, docnbr

Go

++ The pvrec.csv entry used with "Possible Values Import"

"xCostHeader_p0","","","SELECT * FROM xCostHeader where project = @Parm1 AND
docnbr LIKE @parm2 ORDER BY project,
docnbr","xCostHeader","xCostHeader.docnbr;Docnbr;0;0","xCostHeader.project;Building;0;0","xCostHeader.effectDate;Effective Date;0;0"

-----
At the moment, I don't have DBNav or PV filled on the project field -
eventually I would like to make sure that users enter only valid project
numbers. I do have xCostHeader_p0 on the PV property of the docnbr field,
with @parm1 coming from the project number. I've tried to wildcard @parm1,
but it makes no difference.

Paul S Phillips

unread,
Aug 3, 2010, 4:53:03 PM8/3/10
to
Hi Mary,

Things you might check first:

1. Your PVChkFetch is referring to the cBuilding control - I'm not sure this
was intended. Usually the underlying control of the PV event is passed as the
first argument. You can also put PNULL to implicitly pass the underlying
control. The code in the sample will use the cBuilding control's PV SQL, not
cDocNbr.

2. If DocNbr is unique across the header table, your thought about removing
project from the key might be a good idea unless in your screen design you
want the user to first choose a project, and then choose a document (filtered
for just the chosen project). Fewer keys in the UI make the screen design
easier to create and troubleshoot. Depending on the reports and other screens
interacting with the table, though, you might need a secondary index on
project and DocNbr for performance.

I've seen error 10262 occur in two scenarios before:

1. I've seen this happen when the tab order for fields in the UI marked as
key fields in their level property doesn't match the database field order in
the table key (or clustered index if there are no keys defined in the table).
You might be aware that the system will load the record for a level after the
value of the last key field has been set. This retrieval occurs in the PVChk
event, as you have coded using the PVChkFetch API call. The tab order is very
important for key fields.

2. I believe that there must be at least one SQLFetch*, PVChkFetch*, or
DBNavFetch* on a given level's cursor prior to the update control events
firing (e.g. the Update1_Update Event). Since you aren't using a custom
Update1_Update event in your code the SL Kernel does it implicitly in the
background.

If the SL kernel gets to the update event and tries to insert (or update) a
record from the level's buffer via the level's cursor, but there was no prior
SELECT on the cursor, the kernel throws the 10262 error. A given cursor must
be 'primed' or 'initialized' by a database SELECT call. Where it gets
difficult is that sometimes the SL kernel will do it behind the scenes
automatically. Though I know the circumstances of when the error will happen,
I haven't found a way to specifically address it. It may be a result of a
minor problem in the SQL code, the tab order on key fields, the PVChkFetch,
or something else the SL kernel APIs don't like. Perhaps another SL developer
knows the solution.

There have been some cases where all else failed and I had to resort to a
dummy fetch call in the Form_Load event, such as:

RetVal = SqlFetch1(csr_MyCursor, "SELECT * FROM xMyCustomTable WHERE 0=1",
bxMyCustomTable)

That feels like cheating, and I know there was something wrong somewhere in
my code, but in that case I just couldn't find the problem and had to go with
a workaround. I suggest looking into the other things first, and then use the
dummy fetch as a last resort.

There are a lot of things that have to be set just right in both the screen
and SQL, but unfortunately they are not well-documented. I keep notes for
each error message and how it was eventually solved, which I highly recommend
as it helps a lot over time. Also as you found, the debugger can't step into
the SL kernel functions (it's still not .Net code), so this is one of those
cryptic error messages that a developer must solve from experience or brute
force.

Mary L

unread,
Aug 3, 2010, 10:14:03 PM8/3/10
to
Thank you Paul, cBuilding is not supposed to be in that PVChkFetch call.
That is what I get for copying and pasting instead of just re-typing the
code. I don't get the 10262 error message anymore, but I can't use the
screen to create a new cost sheet either - it will only let me update
existing cost sheets (which of course, don't really exist yet ... the old
chicken and the egg problem). I'm getting System Error 9 - Item not found,
please reenter. I'm closer than I was this morning though. Any ideas?

I'll take your advice on changing the table for just the one primary key.

Ultimately, I would like my screen to work rather similarly to the TM.PTA.00
screen (Project Timesheet with Rate/Amount Entry) in Time and Expense for
Projects module. Someone would start off by keying in the building # (aka
project) and then get a list of cost sheets associated with it when they tab
to the document # field. The docnbr field actually will be (hopefully) an
autonumber field. I just wanted to get the UI up and running with one table
before I went there.

I've never implemented auto-number. I've started trying, hoping it would
take care of my "System Error 9" problem at the same time. Any side-bar
advice on autonumber on this issue would also be appreciated. I've created a
xCostSetup table with a "lastdocnbr" field and a procedure "SELECT lastdocnbr
from xCostSetup" to put in the AutoNbrDefault() function (which placed after
screeninit()). I used SQL Server to directly access the table and add one
row. I've added SetAddr and SqlCursorEx calls in the usual places to set up
the cursor to the xCostSetup table (which is NOLEVEL by the way).

Thanks again,

Barry Flynn

unread,
Aug 4, 2010, 5:38:43 PM8/4/10
to
Mary

<< I'm getting System Error 9 - Item not found,

In the RefNbr Chk event. do a
retval = NoAutoChk

On any field with a PV, the kernel will use the stored peocedure associated
with the PV to do an "existance check".
This is done regardless of whether you used the PV to select a RefNbr, or
whether you just typed one in.
If you enter a RefNbr that doesn't exist, this "existance check" comes up
empty, and you get the error that you have got.

Setting retval to NoAutoChk tells the kernel not to do that "existance
check" - ie it permits you to enter a "new" RefNbr that doesn't already
exist .

A couple of quick comments on AutoNumber.
As I recall it...
The RefNbr / LastRefNbr column in all tables must be 10 characters long.
And, in "this screen" (ie the one in which refnbr's are to be assigned) the
RefNbr's Mask must exactly match the data entered in the "last refnbr"
column in your setup record.
That probably makes no sense to you.
Reading it back, it makes no sense to me..

What I attempted to say is that if the RefNbr Mask in "this screen" is (say)
UUUUUU (six characters) then in the setup table, your "LastRefNbr" must be
entered as (say) "000001" (six characters.)

That probably still doesn't make much sense, so I think I'll quit while I;m
not ahead ... :)

Barry

--

Barry Flynn
Complete Solutions DG


"Mary L" <Ma...@discussions.microsoft.com> wrote in message
news:C6CFC9CA-91B6-4AD2...@microsoft.com...

Mary L

unread,
Aug 4, 2010, 7:18:03 PM8/4/10
to
Actually what you wrote does make sense to me ... the AutoNbrDefault()
description in the Tools for Visual Basic reference made it quite clear that
these fields must be exactly 10 bytes in length, even if I will only use six.
I'm good with that.

I have a detail table linked to the header table by the docnbr. When I go
to key into the detail on a new document, I get System Message 6908 - another
process has already added the item. In the table I now have a row with a
blank docnbr ... not such a good idea. I have a workaround, but I can easily
think of reasons why this is NOT the right way to solve the problem.

What I have now follows this logic: If this a new row, I need to set the
docnbr field equal to the header's value. If the header doesn't have one
yet, pull the value from the Setup table and increment it (assuming that this
is what the header will get ... eventually). Here's the code:

If MaintFlg = NEWROW Then
If bxCostHeader.docnbr = " " Then
bxCostData.docnbr = bxCostSetup.lastdocnbr
IncrStrg(bxCostData.docnbr, 10, 1)
Else
bxCostData.docnbr = bxCostHeader.docnbr
End If
End If

If there is a standard programming method for this situation, I'd appreciate
learning about it.

"Barry Flynn" wrote:

> .
>

Barry Flynn

unread,
Aug 4, 2010, 7:52:32 PM8/4/10
to
Mary

<< If there is a standard programming method for this situation, I'd
appreciate
learning about it.

The AutoNbrDefault call in Form Load should sort this out.
It has parameters for (a) The control being autonumbered, (b) 1st additional
control to receive the number, (c) 2nd additional control.

You should just need to put your grid field (bxCostData.docnbr ??) in that
call as "1st additional field".
If you haven't already got a control for bxCostData.docnbr, you will need to
create one (it can have Visible=false)

Typed in soemthing of a rush - hopr it makes sensed.

Barry

--

Barry Flynn
Complete Solutions DG


"Mary L" <Ma...@discussions.microsoft.com> wrote in message

news:8D3D5205-C5E2-47C1...@microsoft.com...

Mary L

unread,
Aug 5, 2010, 2:33:03 AM8/5/10
to
I feel like I'm so CLOSE. Barry, your advise is right on the money. I had
noted that when I first read the docs, but forgot about it by the time I
wrote the code. Next question ....

I am using the DetailSetup function for my SAFGrid and I want linenbr to be
auto-generated.
mh_xCostData = DetailSetup(CSR_xCostData, SafGrid1,
bxCostData.AddressOf("linenbr"), bxCostData, PNULL, PNULL, PNULL)

When I look at the detail table, the linenbr's for a given docnbr are not
sequential (like I would expect them to be) though the first row is always
-32768. At one point a long time ago I had found that someone used
"AddressOf" before the linenbr field. This gets rid of a NASTY error message
(not even a message number attached to this one - Assertion Failed and then
lots of detail I don't even know how to begin to read). But I think
something is confused because now I can't delete or update existing rows
without getting a SQL Server Message 156.

Thanks for the help.

Barry Flynn

unread,
Aug 5, 2010, 6:21:46 AM8/5/10
to
Mary

<< though the first row is always
> -32768.

That's right.
The general usage of LineNbr is that it is used to enable the grid to be
loaded in the "right sequence".
It is assigned by the kernel ar SAVE time.
In "those sort of screens" it is legal for the user to insert a new grid
line in between two existing grid lines.
Therefore:-
- It is assigned with large gaps between successive grid lines so that there
is plenty of room for lines to be inserted between them.
- If a new grid line is inserted between to existing lines, and there is no
gap between their LineNbr's, then the kernel will re-number existing grid
lines to make room for the newcomer.
- It follows that you cannot rely on the value in the LineNbr field - as a
general rule you should assume that it might change, and therefore it is
probably not a good idea to use it to Join to other tables.
- Nevertheless, I believe that the unique index MUST include LineNbr as its
last field (refer to my ramblings on DBNav below).
- The first number assigned is -32768, and successive gris lines are 256
higher (or some number like that.)

<< At one point a long time ago I had found that someone used
> "AddressOf" before the linenbr field.

I hadn't realized that!
I didn't do that in 6.x & earlier versions.
But, looking at one of those screens which has been through the conversion
to 7.x, I see that the conversion utility has changed it to use the
"addressof" construct.

<< I can't delete or update existing rows
> without getting a SQL Server Message 156.

That's "incorrect syntax blah blah?
I suspect its due to the LineNbr field...

When you use the LineNbr field, the grid DBNav gets a bit odd.
LineNbr will be used as the last parameter passed to the DBNav stored proc.
Lets assume there are two other parms.
So, as you define the DBNav property, LineNbr will be parm3, and will have
the wildcard box checked.
In the proc itself though, you will have 4 parms, the last 2 being @parm3Beg
abd @Parm3End.
(You can probably give them more sensible names - but there are odd places
where it seems you MUST call them names like "@parm3". Not sure if it
applies here.

Anyway, you have 4 parms for the proc - one more than you defined in the
DBNav property.
And in the proc's SQL, you say
and LineNbr >= @parm3beg and LineNbr <= @paem3end.

When loading the grid, the kernel will use values like -32768 and +32767 for
those two parms (or whatever the numbers are for min & max integers.)
(It will use larger numbers if they are "longs" instead of "ints".)
It therefore catches all possible grid lines for "this RefNbr" (or whatever)

But when saving/updating/deleting, it will pass the record's actual LineNbr
in both parameters.
It will therefore catch just one record - the one with that LineNbr.

If you continue to get the error, try using Profiler to see exactly what SQL
the kernel is generating (hoprfully Profiler will show it - it may not if it
"fails to parse correctly)

Hope those ramblings help.

Barry

--

Barry Flynn
Complete Solutions DG


"Mary L" <Ma...@discussions.microsoft.com> wrote in message

news:6BBCB2E7-9CA3-41CB...@microsoft.com...

Mary L

unread,
Aug 5, 2010, 11:36:03 AM8/5/10
to
Thanks for explaining the gap in line numbers.

I had similar coding to what you explained for the linenbr ... I just used
"between" instead of <= and >=. Thanks for the thought though.

There was a second error code sometimes when I tried to update or delete:
Programming Bulletproof Error 10209 - Unique index named xcostdata0 has not
been found for table xcostdata. When I looked at the index (after 6 hours of
sleep) , it was named xcostdetail0, not xcostdata0. "xcostdetail" is a
carryover from an earlier attempt at programming this solution - I had needed
to completely change the table structure so I used a different name. It is
amazing how quickly a little rest can solve some of these problems.

So now ... IT WORKS!

Thank you so much for being there. You don't know how many posts I've
written but never sent because I found my problem as I was typing. It really
does help to have an ear sometimes, even if I only end up talking to myself.

0 new messages