SQLite



  • Hallo zusammen!

    Ich habe folgendes Problem und hofffe mir kann jemand helfen.

    Ich habe ein Programm entwickelt das den MFC wrapper für SQLite verwendet.
    Ich habe 2 funktionen die durch buttons ausgelöst werden.

    Eine Funktion wird im Normalfall zuerst aufgerufen und enthält nur select anweisungen. Diese funktioniert.

    Die zweite funktion verwendet Updateanweisungen und da meldet die DB die fehlermeldung: SQLite_Busy

    wenn ich funktion 2 zuerst aufrufe funktioniert sie.

    Ich weiss das die db gelockt ist durch die selectanweisung in funktion 1.
    Sie sollte aber wieder entsperrt werden wenn die funktion beendet ist.

    In beider funktionen erstelle ich das db objekt als lokale variable und öffne die datei. das heist das nach beenden der 1. Funktionen das db objekt aufgelöst werden sollte und somit die db geschlossen sein sollte.

    Warumm ist sie aber bei aufruf aus der 2.Funktion noch immer gesperrt.

    Kann mann die SQLiteDB auch manuell entsperren.

    Bitte um Antwort
    😕 😡



  • // Einträge in der DB suchen
    void CDBtest3Dlg::OnBnClickedButton1()
    {
       	// TODO: Add your control notification handler code here
        sqlite=new CDbSQLite;
    
    	BOOL fTest = sqlite->Open(m_szDbFile);// Öffnen der Datei
        if (!fTest)// Überprüfen ob öffnen erfolgreich ( Fehlerbehandlung)
        {
           CString szError = _T("Could not open ");
           szError += m_szDbFile;
    	   AfxMessageBox(szError);
        }
    
    	COLORREF colorRED=RGB(255,0,0); // Rote farbe um einträge zu färben
        COLORREF colorBLUE=RGB(0,0,255); // blaue Farbe um einträge zu färben
    
        // LISTE Löschen
        m_listCtrl.DeleteAllItems(); // Mit null init.
        while(m_listCtrl.DeleteColumn(0));// ?
    
        nFields=16; // 16 Elemente werden angezeigt
        CRect rect; // übernimmt die Masse des List Gui
        m_listCtrl.GetWindowRect(&rect); // die grösse der List in GUI ermitteln
        nWidth = rect.Width() * 1 / (nFields+1);  // errechnen der spaltenbreite der listcontrol. nFields+1 wegen der 1.leeren spalte für min max bezeichnung
        nCol = 0; // Spalte
        nRow = 0; // Reihe
    
        m_listCtrl.SetGridLines(true); // Gitternetz erzeugen
    
        CString szText; // übernimmt query und fehlermeldung
    
        // Spaltennamen in listcontrol erstellen
        m_listCtrl.InsertColumn(1, "*", LVCFMT_CENTER, nWidth, 1); // eine leere spalte am anfang wegen min max bezeichnung
    
        for(nCol=0; nCol < nFields; nCol++) 
        {
    	   szText = m_szElementeArray.GetAt(nCol);  // Spalten(elementname) in die variable
           szText.MakeUpper();  // Alles in grossbuchstaben konvertieren
           m_listCtrl.InsertColumn(nCol+2, szText, LVCFMT_CENTER, nWidth, nCol+2); // nCol+2 um die erste leere spalte zu überspringen
        }  // in der liste eine neue spalte(DB: Tabelle) mit kopfname(Tabellenname) erzeugen  
    
        UpdateData(TRUE);// Benutzereingabe einlesen
    
        // Überprüfen ob eine eingabe erfolgt ist
        if(m_eingabeWerkstoff=="")
        {
           szText="!!! ACHTUNG: Bitte Werkstoff eingeben !!!";
    	   m_ausgabe=szText;
    	   UpdateData(FALSE);
    	   AfxMessageBox(szText);
    	   return;
        }
    
        // Abfrage der Werkstofftabelle
        szText.Format(_T("SELECT * FROM werkstoff WHERE werkstoffnr = '%s'"),m_eingabeWerkstoff);
        CSqlStatement* stmt=NULL;
        stmt = sqlite->Statement(szText); // Speichern der abfrage in einer variablen
    
        if (stmt != NULL) // Nur wenn stmt einträge beinhaltet
        {
    	    stmt->NextRow(); // Auf datenebene weitergehen
    	    CString stmtPrüfen=stmt->ValueString(1); // 1 = werkstoffNr
    
    	    if(stmtPrüfen.Compare(m_eingabeWerkstoff)==0)// Wenn werkstoffnummer vorhanden. 1 wäre fehler
    	    {
    		    m_ausgabe="! Werkstoff Gefunden !";
    		    m_kontrProbe=stmt->ValueString(0); // 0 = kontrollprobe eintrag
    		    m_ausgabePfanne=stmt->ValueString(2); // 2 = pfanne leco eintrag
    		    m_ausgabeFA=stmt->ValueString(3); // 3 = FA leco eintrag
    		    m_ausgabeProgramm=stmt->ValueString(4); // 4 = Abfunk programm eintrag
    		    m_ausgabeNotiz=stmt->ValueString(5); // 5 = Notizeintrag
    		    m_listCtrl.InsertItem(1, "MIN"); // eine zeile einfügen für MIN werte
                m_listCtrl.InsertItem(2, "MAX"); // eine zeile einfügen für MAX werte
    
    		    // Einlesen der werte von elemente
    		    CString szMin;
    		    CString szMax;
    
    		    for(nCol=0; nCol < nFields;nCol++)// alle elemente einlesen
    		    {
    
    			    szText.Format(_T("SELECT * FROM '%s' WHERE werkstoffnr = '%s'"),m_szElementeArray.GetAt(nCol),m_eingabeWerkstoff);   
                    stmt = sqlite->Statement(szText); // Speichern der abfrage in einer variablen
    
    			    if(stmt!=NULL)
    			    {
    				    // Min einlesen --------------------------------------------------------
    				    stmt->NextRow(); //datenebene
    				    szMin = stmt->ValueString(1); // 1 = min eintrag
    				    if(szMin.Compare("0")!=1){szMin=_T("-");}//wenn kein eintrag dann mit - ersetzten
                        m_listCtrl.SetItem(0, nCol+1, LVIF_TEXT, szMin,0,0,0,0); //0 = erste(min) zeile 
    
    				    // Wenn der eintrag einen wert enthält und nicht '-' dann blau färben
    				    if(szMin.Compare(_T("-"))==1)
    				    {
    				        m_listCtrl.SetItemBkColor(0, nCol+1, colorBLUE, TRUE); 
    				    }
                        // Min einlesen ENDE -----------------------------------------------------
    
       				    // Max einlesen ----------------------------------------------------------
                        szMax = stmt->ValueString(2); // 2 = max eintrag
    				    if(szMax.Compare("0")!=1){szMax=_T("-");}
                        m_listCtrl.SetItem(1, nCol+1, LVIF_TEXT, szMax,0,0,0,0); // 1 ist 2.(max) zeile
    
    				    // Wenn der eintrag einen wert enthält und nicht '-' dann rot färben
    				    if(szMax.Compare(_T("-"))==1)
    				    {
    				        m_listCtrl.SetItemBkColor(1, nCol+1, colorRED, TRUE); 
    				    }
                        // Max einlesen ENDE -----------------------------------------------------
    			    }
    			    else
    			    {
                        AfxMessageBox("konnte Tabelle für Werkstoffe nicht abfragen");
    				    return;
    			    }
    		    }
    
    	   }
    	   else // alle variablen der Ausgabe zurücksetzen
    	   {
    		   m_kontrProbe="";
    		   m_ausgabePfanne="";
    		   m_ausgabeFA="";
    		   m_ausgabeProgramm="";
    		   m_ausgabeNotiz="";
    		   AfxMessageBox("ACHTUNG !  WERKSTOFF NICHT VORHANDEN!");
    		   m_ausgabe="ACHTUNG !  WERKSTOFF NICHT VORHANDEN!";
    	   }
    
       }
    
       UpdateData(FALSE);
    
       delete(sqlite);
       sqlite=NULL;
    }
    
    // Einträge in der DB ändern
    void CDBtest3Dlg::OnBnClickedAendern()
    {
    
        sqlite=new CDbSQLite;
        bool fTest; // übernimmt ob der DB rückgabe erfolgreich
    
    	fTest = sqlite->Open(m_szDbFile);// Öffnen der Datei
        if (!fTest)// Überprüfen ob öffnen erfolgreich ( Fehlerbehandlung)
        {
           CString szError = _T("Could not open ");
           szError += m_szDbFile;
    	   AfxMessageBox(szError);
        }
    
    	UpdateData(TRUE);
    
    	CString szText; // übernimmt query und fehlermeldung
    
    	szText.Format(_T("UPDATE werkstoff SET probe='%s' WHERE werkstoffnr = '%s'"),m_kontrProbe,m_eingabeWerkstoff);
    
        fTest = sqlite->DirectStatement(szText); 
    
    	delete(sqlite);
    	sqlite=NULL;
    
    }
    

    Wie gesagt: Funktion 2 funktioniert solange ich nicht Funktion 1 aufrufe.
    Wenn ich Funktion 1 aufrufe wird die DB gesperrt und leider nicht nach beenden der Funktion freigegeben. Besser gesagt Funktionieren die Funktionen Aber der SQL-Befehl UPDATE gibt die Fehlermeldung: SQLite_Busy zurück.
    Das heisst die DatenBank lässt mich nach aufruf der 1.Funktion keine Schreibbefehle mehr aussführen.
    Habe es auch versucht ohne die CDbSQLite objekte als Zeiger zu erstellen und funktioniert auch nicht. Habe es mit Zeiger versucht da ich annahm das das Objekt vieleicht nicht richtig aufgelöst wird und somit der Destruktor des Objekts nicht aufgerufen wird. Aber auch nach expliziertem deleten gibt SQLite die Datei nicht frei. Ich muss noch erwähnen das der Destruktor die finalize und DB_Close aufrufe enthält.
    In einem mitgelieferten Beispiel des Wrappers funktioniert die vorgehensweise.



  • Weiß zwar nicht ob es das gibt aber bevor du delete(sqlite); aufrufst solltest du die DB schließen.



  • Danke für die Antwort, aber leider nutzlos. Der Destruktor des CDbSQLite Klasse übernimmt dies! Also weiterhelfen bitte!



  • Doppelppost


Anmelden zum Antworten