Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

FetchLock not locking the row (v53A) 1

Status
Not open for further replies.

RyanLSMP

Programmer
Mar 13, 2006
4
US
I’m new to AccPac programming but have had smooth sailing up to this point. I’m currently calling the AccPac COMAPI (v5.3.a) from a C++ program. I can access the database and manipulate the data there.

My snag is when I call FetchLock. After calling FetchLock the row is *not* locked until I actually call Update. I have even gone so far as to call FetchLock and then edit the row with another program, invalidating the fetched information. The update and subsequent transaction complete with no errors. I’m hoping there is something I am doing wrong with my calling.

While FetchLock is documented to return a Boolean value I get back a -1 (0xFFFFFFFF). While this is a valid true for a boolean, it is also the error code for VC_WARNING. When I access the error object after getting the Boolean back, there are no errors logged.

I’ve included the calling sequence I am using. All the calls are completing with no errors and no exceptions thrown.

Is this a known bug in the Accpac API, or am I simply using it incorrectly?

Thanks,
Ryan.

Call Sequence: (NOTE: I have removed error checking)
Code:
//Create the instance.
Session.CreateInstance(__uuidof(AccpacCOMAPI::AccpacSession));
//Initialize and open the session.
Session->Init(_T(“”), _T(“XZ”), _T(“XZ1000”), _T(“53A”));
Session->Open(_T(“USER”), _T(“Pass”), _T(“DB Name”), Date, 0, _T(“”));
//Open a DBLink to the company.
DBLink = Session->OpenDBLink(AccpacCOMAPI::DBLINK_COMPANY, AccpacCOMAPI::DBLINK_FLG_READWRITE);
//Open a view and retrieve the fields.
View = DBLink->OpenView2(_T(“MX0001”), NULL);
View->Init();
Fields = View->Fields;

//---------------------Beginning of fetchlock code------------------
DBLink->TransactionBegin(&TransactionLevel);
View->Browse(_T(“SQL Search string”));
View->FetchLock(); //Note: The row is *not* locked at this point. 
//Edit Information
View->Update(); //Note: At this point the row is locked.
View->UnLock(); //Note: This does not actually unlock the row.
DBLink->TransactionCommit(&TransactionLevel); //Note: This unlocks the row.
//--------------------End Fetchlock Code-----------------------------
Session->Close();
 
Fetchlock returns zero if succesfull, else the current record is not valid.
There is no reference to a return code of -1, only 0 and greater.
Are you setting the index for the view? Use Order to set the index.
 
I have tried both setting the index for the view and using the default. (The Index to use is index 0, which is the default anyway). FetchLock's reflex did not change in either case.

As for the return code, Fetchlock is defined to return a bool (0 for false, !0 for true). Most of the api returns a HRESULT where 0 is success, but Fetchlock is listed as different. Now with that being said, a -1 (0xffff) is a valid true value. I have double checked this by both watching for a thrown exception and checking the view's lastreturncode (it was VS_SUCCESS). All the signs I know how to check list the function returning as successful, but when checked the row is not locked.

The FetchLock definition located in the a4wcomex.tli is:
Code:
inline VARIANT_BOOL IAccpacView::FetchLock ( ) {
    VARIANT_BOOL _result;
    HRESULT _hr = raw_FetchLock(&_result);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _result;
}

 
OK, I was reading the SDK documentation which states it the other way round, never mind.
Delving deeper I found that the record is only locked when a change is made, not when the fetchlock is done, in other words pessimistic record locking. And the lock is released when the transaction in committed, which you observed. So according to the SDK docs it is working as designed (but maybe not as expected).
The recommended procedure is to use Fetch and Update instead of FetchLock and Update, but don't ask me why 'cause I dunno, that's what the docs say.
I've never used FetchLock in the 10 years I have been writing Accpac stuff.
 
From the SDK Programming Guide:
If you are updating a single record use Fetch, if you are updating multiple records or deleting a record use FetchLock.
 
The problem with using fetch to update a single record is that it leaves a race condition in the code in a multi-user environment. For example:

User 1: Fetches data to update - 1
User 2: Fetches data to update - 1
User 1: Updates data - (Adds 1) - 2
User 2: Updates data - (Adds 4) - 5

Data is now 5 when it should be 6. Fetchlock solves this problem by only allowing a single user to hold the row. In this cause User 2 would have to wait to update the data. This condition is still in the code if the row is only locked when updated.

As I am in a multi-user environment I have no choice but to use fetchlock.

Thanks,
Ryan

 
Not true, Accpac deals with that internally.

I did a simple test with Fetch and Update on 2 computers.

I fetched a record on computer 1
I fetched the same record on computer 2, modified something and updated the record.
I modified the record on computer 1 and when I did the update I got the message "record has been modified..." which was what I expected.

When you have concurrent updates of a record the first update of the record will be accepted, any others will be rejected.
 
Agreed, using Fetch produces that error, but FetchLock does not. That atleast saves me from having to put a trigger into the database to fix this.

Is there any way to ensure that the first user to get the data has exclusive access to that data?

User 1: Starts transaction
User 1: Gains exclusive access and Fetches data (atomic)
User 2: Attempts to fetch data and must block/error.
User 1: Completes data and Updates/Ends transaction.
User 2: Returns from blocking and gets data.
 
I have a little problem accessing the field information in c++

View = DBLink->OpenView2(_T(“AR0024”), NULL);
View->Init();
Fields = View->Fields;

what do you use to get the value of the fields using the FieldID ?

THANKS in advance

Jo

** sorry to hijack the tread, but it is the only reference i could find on C++...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top