CRecordset MoveNext/MovePrev Problem



  • Hi Leute!

    Ich habe eine von CRecordset abgeleitete Klasse mit der ich Daten aus einer Interbase-Datenbank lese. Das Recordset ist vom Typ CRecordset::snapshot
    und unterstützt auch das Scrolling in zwei Richtungen. Ich kann auch problemlos im Recordset navigieren. Jedoch verhalten sich die Move-Funktionen sehr seltsam.
    Das erste Phänomen:
    Ich Scrolle durchs Recordset bis ans Ende der Datei. Wenn Recordset.IsEOF() ein True zurückgibt stoppe ich das Scrolling. Das funktioniert beim ersten mal super. Scrolle ich einen Datensatz zurück und dann wieder vor, so das ich wieder am Ende der Datei stehe, gibt es plötzlich eine Exception im Ausgabe-Fenster in dem Augenblick, in dem MoveNext() aufgerufen wird. Woran kann das liegen ?
    Das zweite Problem ist noch seltsamer:
    Rufe ich MoveLast oder MoveFirst auf springt das Recordset jeweils korrekt auf den ersten/bzw letzten Satz im Set. Will ich mich dann mit MoveNext/MovePrev eine Zeile vor/zurück bewegen dauert es ewig bis das Ergebnis da ist. Ausserdem stehe ich dann auf dem falschen Satz. Ich habe eine Tabelle mit genau 10.000 Sätzen. Rufe ich MoveLast auf, stehe ich auf der 10.000, mach ich dann einen MovePrev, stehe ich nach einigen Sekunden des Wartens plötzlich auf
    9.000 😮 😕
    Plz help!

    Noch einige Infos:
    DB ist Interbase, Recordset ist Snapshot, CursorLib ist aktiv



  • Nicht schlecht wäre ein bisschen Code, wenn du irgendwo was mit den navigationen machst. Denn wenn du die Funktionen nicht überlädst, tun sie eigentlich schon das was sie tun sollen! Das mit der langen Wartezeit ist nicht außergewöhnlich, das kenne ich sowohl von access als auch von MS-SQL-Server. Woher das kommt kann viele Gründe haben, aber wenn ich richtig liege musst du dich damit abfinden.



  • Hier ist der Code zum Scrollen:

    bool CMySet::SkipRecord(int nDirection)
    {
        if (nDirection >= 0)
        {
            if (IsEOF())
                return false;
    
            MoveNext();
        }
        else
        {
            if (IsBOF())
                return false;
    
            MovePrev();
        }
    
        return true;
    }
    

    Zum Thema Geschwindigkeit: Das Scrollen im Set ist super schnell. Nur wenn ich irgendwann ein MoveLast/First mache und dann wieder einzelne Sätze "skippen" will, ist es plötzlich unnormal langsam.



  • Also ich meine auf erstes Phänomen kannst du folgendes anwenden:

    CRecordView::OnUpdateRecordLast(pCmdUI);
    

    Ist wenn ich richtig liege auch abfrage auf isEOF nur der gleichzeiten deaktivierung der Menüpunkte bzw Button Fkt. Also ich hab mir mal nen step 10 gemacht und das sieht in etwa so aus:

    ///////////////////////////////////////////////////////////////////////7
    // bewegen durch den Recordset
    /////////
    // 10 Datensätze vorwärts
    void CACRSQLView::OnRecordNext10() 
    {
    	m_pSet->Move(10);
    	if(m_pSet->IsEOF())
    		m_pSet->MoveLast();
    	UpdateData(false);
    }
    // 10 Datensätze Rückwärts
    void CACRSQLView::OnRecordPrev10() 
    {
    	m_pSet->Move(-10);
    	if(m_pSet->IsBOF())
    		m_pSet->MoveFirst();
    	UpdateData(false);
    }
    // de- / aktivieren wenn 10 Datensätze vor nicht erlaubt
    void CACRSQLView::OnUpdateRecordNext10(CCmdUI* pCmdUI) 
    {
    	CRecordView::OnUpdateRecordLast(pCmdUI);	
    }
    // de- / aktivieren wenn 10 Datensätze zurück nicht erlaubt
    void CACRSQLView::OnUpdateRecordPrev10(CCmdUI* pCmdUI) 
    {
    	CRecordView::OnUpdateRecordFirst(pCmdUI);	
    }
    

    Das Problem ist wenn du abfragst isEOF dann ist er in dem Moment noch nicht EOF aber wenn du dann MoveNext machst ist er EOF zeig mal bitte welches Assert sich meldet.
    Zur Geschwindigkeit glaube ich an folgendes, weiß es allerdings nicht sicher. Wenn du movest, dann zeigt der Cursor auf den nächsten gewünschten Datensatz. Sprich wenn du machst move Last zeigt er nur dorthin. movest du nun von dort aus, verschiebt er dann der Cursor auf last, und das ist das was Zeit kostet.
    Warum du bei move prev plötzlich bei 9000 stehst kann ich dir so leider nciht sagen.



  • Hi nochmal, das geht schon besser mit deinem Code. Die Exception in der Ausgabe kriege ich allerdings immernoch wenn ich auf dem ersten stehe und einen zurück-skippen will (was ja BOF wäre, wenn er es zulassen würde).

    Nicht abgefangene Ausnahme in DBTest.exe (KERNEL32.DLL): 0xE06D7363: Microsoft C++ Exception.
    

    🙄



  • öhm hast du deine eigenen Buttons?
    Deaktivierst du die denn wenn BOF?
    Versuch mal dich bis kurz vor die Exception hin zu debuggen, weil allein mit der Fehlermelung kann ich zumindest nicht viel anfangen. Zeig mal welche Zeile die letzte ausgeführte in deinem Code ist und welche es in der MFC ist. (vielleicht paar davor noch mit dazu)



  • Also, die Funktion die den Fehler verursacht heisst SQLExtendedFetch und wird irgendwann innerhalb meiner MoveNext() aufgerufen. (Man muss sich durch-debuggen, von MoveNext über Fetch() bis zu dieser Stelle - Das ist dann schon die tiefste Schicht und man kann auch leider nicht mehr in die SQLExtendedFetch einspringen)



  • hm so blind kann ich dir leider nicht weiter helfen, magst du mir dein Projekt mal schicken? Vielleicht weiß ja jemand anders so weiter aber ich nciht. 😞


Anmelden zum Antworten