CRowset and MovePrev

What is wrong with this code...


HRESULT hr = m_pSet->MoveLast();
while (hr == S_OK)
{
hr = m_pSet->MovePrev();
}


It is *supposed* to step backwards through the rowset once only, but what I find is that it just keeps going round and round infinitely and never exits the loop?!?

I am completely stumped... what am I missing here? (something obvious no doubt)

I tested the above code by creating a MFC app using the wizard to hook up an OLE DB connection to a Jet database. I am using VS.NET on Windows XP btw.
LVL 2
paulburnsAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
DanRollinsConnect With a Mentor Commented:
It really helps if you provide a contest.

In the file ATLDBCLI.H, we see that MovePrev is defined as :

HRESULT MovePrev()
{
     return MoveNext(-2, true); // delta, bForward
}

And the relvant part of MoveNext is:

HRESULT MoveNext(LONG lSkip, bool bForward)
      hr = m_spRowset->GetNextRows(NULL, lSkip, (bForward) ? 1 : -1, &ulRowsFetched, &phRow);

which is:
    GetNextRows( 0, -2, 1, &nCnt, &phRow )

So lSkip is -2 and cRows is 1 (requesting forward motion).  

The dox mention that providers implement skipping in various ways.  It seems that the Jet provider is a little wacky or perhaps the template is wrong (why not -1?  why move 'forward by -2 rather than move backward by 1?  

I'd have to guess that it rowset provider moves past the beginning and automatically cycles to the end and so sees no error.

Anyway, I'd try changing your code to this:

//----------------------- I did not test this code.
while (hr == S_OK)
{
     hr = m_pSet->MoveNext( 1, false );
    // or maybe
    // hr = m_pSet->MoveNext( 2, false );
}

That way the low-level GetNextRows() call will pass -1 as the third parameter, which tells the provider to skip backwards.

But the real solution is to check IsBOF() on each loop.

-- Dan
0
 
GGRUNDYCommented:
maybe you need

while (hr==S_OK && !m_pSet->IsBOF())
0
 
DanRollinsCommented:
The docs ward agains using CRecordset::MovePrev() without chcking IsBOF().  So the best way to cycle backward would be analogus to
while(!crs.IsEOF() ) { ...crs.MoveNext()... }

while ( !m_pSet->IsBOF() ){
    m_pSet->MovePrev();
}

What I don't understand is why this is not giving you a compiler error:

     hr= m_pSet->MovePrev();

The CRecordset and CDaoRecordset member fns MovePrev() return void, and that attempt to assign the 'return value' of a void fn to your hr variable, is a clear error.  If you are using ADO _Recordsets, there is no MovePrev() fn (only MovePrevious).  

Can you explain?

-- Dan
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
paulburnsAuthor Commented:
Maybe I wasn't clear, I am using the OLE DB template classes... CRowset, not CRecordset. According to the docs MovePrev should return DB_S_ENDOFROWSET (i.e. something other than S_OK)  when it gets to the end or beginning of the rowset.


If I try this code to step *forward* through the rowset then it  works....


HRESULT hr = m_pSet->MoveFirst();
while (hr == S_OK)
{
hr = m_pSet->MoveNext();
}


It is only when stepping *backwards* through the rowset that I get the problem described.

0
 
paulburnsAuthor Commented:
Hi Dan, you aren't Henry's brother by any chance? ;) ...ah poor joke I bet you get that all the time.

Anyway, after some experimenting I found MoveNext(0, false) worked. Now why the hell wasn't MovePrev
implemented this way?!

thanks.
0
 
DanRollinsCommented:
OLE DB is designed to be very general.  I think that the template is implemented that way because some data sources have a lot of trouble moving backwards through a rowset (even though I can't think of why the template's handling would be any safer or more efficient).

-- Dan

BTW, you could have easily solved this yourself by single-stepping through the MovePrev fn; it's only about 10 lines of code.  VC++ debugger is excellent for solving mysteries.
0
All Courses

From novice to tech pro — start learning today.