I am getting this error when calling RefreshAll.
I have a probinding source defined which is the datasource for an IG ultragrid. The datasource is two temp tables (tData and tData1) that have a relation defined (the temp table and dataset def is below).
For performance reasons only the top level table (tData) is populated along with a single record in the child table (tData1).
In the BeforeRowExpanded event for the grid, addition child records (tData) may be populated.
The procedure that populates the additional child records is RefreshData1 and exists in a persistent procedure (myProcHandle) that can be run locally or on the appserver.
The dataset dsData is passed as an input-output param.
I have changed the code in RefreshData1 so that it does nothing but return (IF TRUE THEN RETURN at the top of the procedure) and the error still persists even thought the contents of the dataset remain unchanged.
I suspect that there is some data condition that is causing the behavior because if I eliminate some of the records in the initial fill of the top level temp table, the error does not occur.
WHAT I AM LOOKING FOR IS SCENARIOS THAT WOULD CAUSE THIS ERROR.
Currently, I don't know what approach to take.
Here is the guts of the code...
RefreshData1 method is called from the BeforeRowExpanded event method...
IF VALID-HANDLE(myProcHandle) THEN DO:
RefreshData1(INPUT rRowid, INPUT cPoNum, INPUT cWhsNum).
bindingSource1:RefreshAll().
ultraGrid1:Refresh().
ultraGrid1:Rows:Refresh(Infragistics.Win.UltraWinGrid.RefreshRow:ReloadData).
END.
METHOD PRIVATE VOID RefreshData1
( INPUT rRowid AS ROWID,
INPUT cPoNum AS CHARACTER,
INPUT cWhsNum AS CHARACTER).
RUN RefreshData1 IN myProcHandle
( INPUT rRowid,
INPUT cPoNum,
INPUT cWhsNum,
INPUT FormGlobals:gApGroup,
INPUT-OUTPUT DATASET dsData).
RETURN.
END METHOD. /* RefreshData1 */
Here is the datasource definition...
DEFINE TEMP-TABLE tData NO-UNDO
FIELD tDbRowid AS ROWID
FIELD tWhsNum AS CHARACTER
FIELD tPoNum AS CHARACTER
FIELD tQtyOrd AS DECIMAL
FIELD tQtyRet AS DECIMAL
FIELD tDispUm AS CHARACTER
FIELD tVendNum AS CHARACTER
FIELD tVendName AS CHARACTER
FIELD tPoType AS CHARACTER
FIELD tPoStat AS CHARACTER
FIELD tPoDate AS DATE
FIELD tPoExpectDate AS DATE
FIELD tDateFirm AS LOGICAL
FIELD tBuyer AS CHARACTER
FIELD tOrderNum AS INTEGER
FIELD tShipType AS CHARACTER
FIELD tStocked AS CHARACTER
FIELD tOpenTotal AS DECIMAL
FIELD tRcvdTotal AS DECIMAL
FIELD tTaxCode AS CHARACTER
FIELD tWeight AS DECIMAL
FIELD tTermsCode AS CHARACTER
INDEX idx1 IS PRIMARY UNIQUE tDbRowid tPoDate DESCENDING tWhsNum tPoNum
INDEX idx2 tDbRowid tPoStat tPoDate.
DEFINE TEMP-TABLE tData1 NO-UNDO
FIELD tDbRowid AS ROWID
FIELD tPoNum AS CHARACTER
FIELD tWhsNum AS CHARACTER
FIELD tPoLineNum AS INTEGER
FIELD tSku AS CHARACTER
FIELD tSkuDesc AS CHARACTER
FIELD tQtyOrd AS DECIMAL
FIELD tQtyRet AS DECIMAL
FIELD tBuyUm AS CHARACTER
FIELD tEntCost AS DECIMAL
FIELD tCostUm AS CHARACTER
FIELD tCompNum AS INTEGER
INDEX idx1 IS PRIMARY tPoLineNum tCompNum.
DEFINE DATASET dsData FOR tData, tData1
DATA-RELATION Relationship FOR tData,tData1
RELATION-FIELDS (tDbRowid, tDbRowid, tPoNum, tPoNum, tWhsNum, tWhsNum).
Since this is a refresh functionality, can I assume that you are deleting temp-table in the process? When you delete a temp-table record, the corresponding bindingsource entry is not removed. So when the UltraGrid triggers a redraw you will get the error.
You can try something like this;
temp = grid:DataSource.
grid:DataSource = ?.
/* refresh temp-table */
grid:DataSource = temp.
Also,
If your INPUT-OUTPUT parameter will eventually cross the AppServer boundary, you also get the same error.
I'd rather reopen the query to fix the queries result list or DELETE-RESULT-LIST-ENTRY to remove the specific malicious entry.
It's more likely an issue of the BindingSource than the Grid.
Re-opening a query won't help, since the problem is on the currently bound records. DELETE-RESULT-LIST-ENTRY is not always feasible when dealing with n-tier architecture. It's also not elegant when deleting multiple records at once.
You cannot delete multiple records at once. You always delete one after the other - and can DELETE-RESULT-LIST-ENTRY one after the other. No matter in which architecture.
DELETE-RESULT-LIST-ENTRY requires passing the query handle around. Most n-tier architectures use temp-table and dataset as data carrier. I understand that you only delete one record at a time that's why I said "not elegant when you have to delete multiple records" and not impossible. And it's not always feasible when you are delegating work across appserver or webservice API boundaries.
Absoltely agree with you.
But no matter what you do, the BindingSource works with a query; on a temp-table or on ProDataset temp-tables using an explicit query or an implicit query such as the TOP-NAV-QUERY or the Query of a ProDataset Relation.
The post is why the user is getting "no record avail". The most probably answer is that the temp-table that is bound to the grid is being manipulated, and the bindingsource has no way of knowing what happened.
The post is why the user is getting "no record avail"
... during a call to the BindingSource's RefreshAll() method.
When the record is deleted, it's still contained in the result list of the query (whatever Query the BindingSource uses, see my previous post). The only way to get a record out of the query's result-list is the DELETE-RESULT-LIST-ENTRY method or re-opening the query. Period.
Please try it out or read the binding source sample in the GUI for .NET Developers guide.
I have not had a chance to revisit the issue outlined in this post. I have gotten around the issue temporariily by building up all of the child data on the front end versus building it up in the BeforeRowExpanded event. I will review the your comments and see if I can figure out the problem.
A couple comments
1. This appears to be data dependent - that is depending on what parent records are selected, the error may not occur
2. The error occurs regardless if running the data gathering routine and filling the dataset over thge appserver or on the client and passing back the dataset handle so I don't think the appserver boundary has anything to do with it
3. No tData records are being deleted - the only action is that tData1 (child records) are being added
We've dealing with this issue for quite sometimes now. I would like to know what you find out to add to my growing list of when this errors can show up. The problem seems to be related to the UltraGrid repaint in between what you are doing. It's a little touchy because sometimes the code seems to proceed nicely until you add a messagebox, or you call one of UltraGrid's methods.
So far, I noticed this problem in the following cases;
- You might get this when you input-output along the appserver boundary (I pass a copy).
- You will get this when you directly delete a record (I normally close the query then delete to handle this)
- You called a method on the client where the query is currently scope with an INPUT and if the Ultragrid repaint gets trigger before you can reopen the query. (if the first thing you do in the method is to reopen the query, it seems to work fine)
- When cancelling out of UltraGrid update mode and you have an embedded editor that is in edit mode, the CancelCreateRow can trigger this error (related to delete, unsubscribe then resubscribe to fix)
- The temp-table is built in window A, window A passes the temp-table to window B then window A is closed. (this has something to do with the widget pool)
Except for the record deletion and CancelCreateRow, most of the above cases are related to creation of new temp-table instance that is different from what is currently bound. It's not set in stone, but I think this happens when the UltraGrid repaints in between the process.
When you Input-output the temp-table across the AppServer boundary, the rowids of the temp-table records may change, which invalidates the query result list. Thus, you will have to reopen the query to avoid trouble with the binding source.
Executing the following code before calling the RefreshAll method solves the problem...
hQry = DATASET dsData:HANDLE:TOP-NAV-QUERY(1).
hQry:QUERY-PREPARE(pWhereClause).
hQry:QUERY-OPEN().
IF NOT(VALID-HANDLE(bindingSource1:HANDLE)) THEN
bindingSource1:HANDLE = DATASET dsData:HANDLE.
bindingSource1:REFRESH().
I think the QUERY-OPEN triggers a refresh automatically.