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