2012-06-08 164 views
2

我正在寫一個聯繫簿應用程序。聯繫人存儲在qsqlite數據庫中,並使用QSqlQueryModel顯示。無法更新QSqlite數據庫 - 數據庫鎖定無法獲取行

QueryModel默認運行一個顯示所有聯繫人的查詢。聯繫人可以編輯和刪除。

當用戶在搜索字段中輸入名稱時,會運行SearchQuery並僅顯示與搜索條件匹配的聯繫人。問題是我無法編輯或刪除這些聯繫人。我得到一個錯誤,說數據庫被鎖定,無法獲取行。

我不明白爲什麼會發生這種情況。如果我可以編輯/刪除默認查詢的結果,那麼我應該可以編輯/刪除搜索查詢的結果。

下面是代碼:

  • 構造

  • 在搜索聯繫人

  • 拆卸觸點

構造函數(相關部分)

OpenDatabase(); 

    DefaultModelQuery.append("SELECT Id,FirstName||' '||LastName AS FullName,"); 
    DefaultModelQuery.append("FirstName,LastName,Email,HomeNumber,WorkNumber,MobileNumber,Address,City,Country,Birthdate FROM Contacts "); 
    DefaultModelQuery.append("ORDER BY FirstName;"); 

    QSqlQuery Query(DefaultModelQuery); 

    ActiveQuery = Query; 
    Model = new QSqlQueryModel(this); 
    Model->setQuery(ActiveQuery); 

    ui->listView->setModel(Model); 
    ui->listView->setModelColumn(1); 

搜索聯繫

void Contacts::SearchContact() 
{ 
    /*1. Read Search Term 
     2. Decide Type 
     3. Generate Query 
     4. Execute Query. 
     5. If No results, return 
     6. If resutls, update Model, show first result. 
     */ 

    //STEP 1: Read Search Term. 
    QString SearchTerm = ui->SearchLineEdit->text(); 

    if(SearchTerm.isEmpty()) 
     return; 

    /*STEP 2. Decide Type 
     Type n : Name 
     Type e : Email 
     Type p : Number 
     */ 
    char QueryType; 

    if(SearchTerm.contains(QRegExp("[A-za-z-]+"))) 
    { 
     if(SearchTerm.contains("@")) 
      QueryType = 'e'; 
     else 
      QueryType = 'n'; 
    }else if(SearchTerm.contains(QRegExp("[0-9]+"))) 
     QueryType = 'p'; 
    else 
     QueryType = 'n'; 


    //STEP 3: Generate Query 
    QSqlQuery SearchQuery; 

    switch(QueryType) 
    { 
    case 'n': 
    { 
     QStringList Names = SearchTerm.split(" "); 
     if(Names.size()>=2) 
     { 
      qDebug()<<QString("Searching for %1 %2").arg(Names.first(),Names.last()); 
      SearchQuery.prepare("SELECT Id,FirstName||' '||LastName AS FullName,FirstName,LastName,Email,HomeNumber,MobileNumber,WorkNumber,Address,City,Country,Birthdate FROM CONTACTS WHERE FirstName=:f AND LastName=:l ORDER BY FirstName"); 
      SearchQuery.bindValue(":f",Names.first()); 
      SearchQuery.bindValue(":l",Names.last()); 
     }else 
     { 
      qDebug()<<QString("Searching for %1").arg(Names.first()); 
      SearchQuery.prepare("SELECT Id,FirstName||' '||LastName AS FullName,FirstName,LastName,Email,HomeNumber,MobileNumber,WorkNumber,Address,City,Country,Birthdate FROM CONTACTS WHERE FirstName=:f OR LastName=:l ORDER BY FirstName"); 
      SearchQuery.bindValue(":f",Names.first()); 
      SearchQuery.bindValue(":l",Names.first()); 
     } 
     break; 
    } 

    case 'e': 
    { 
     QString Email = SearchTerm.trimmed(); 
     SearchQuery.prepare("SELECT Id,FirstName||' '||LastName AS FullName,FirstName,LastName,Email,HomeNumber,MobileNumber,WorkNumber,Address,City,Country,Birthdate FROM CONTACTS WHERE Email=:e ORDER BY FirstName"); 
     SearchQuery.bindValue(":e",Email); 
     break; 
    } 

    case 'p': 
    { 
     QString Number = SearchTerm.trimmed(); 
     SearchQuery.prepare("SELECT Id,FirstName||' '||LastName AS FullName,FirstName,LastName,Email,HomeNumber,MobileNumber,WorkNumber,Address,City,Country,Birthdate FROM CONTACTS WHERE HomeNumber=:h OR WorkNumber=:w OR MobileNumber=:m ORDER BY FirstName"); 
     SearchQuery.bindValue(":h",Number); 
     SearchQuery.bindValue(":m",Number); 
     SearchQuery.bindValue(":w",Number); 
     break; 
    } 
    } 

    //STEP 4: Execute Query 
    if(!SearchQuery.exec()) 
    { 
     qDebug()<<QueryType<<": "<<SearchQuery.lastError().text(); 
     QMessageBox::information(this, 
           tr("Search Error"), 
           tr("The following error occured while trying to search contacts:\nError: %1").arg(SearchQuery.lastError().text())); 
     return; 
    } 

    //STEP 5: If no results, return; 

    /*Note: 
    I used the QSqlQuery::first() method here to check if there are any result or not. 
    I doubt this is efficient, because the function probably invovles unnecessary steps & resources. 
    So the following code could be made more efficient. 

    I can't use QSqlQuery::size() because it always returns -1. 
     */ 

    if(!SearchQuery.first()) 
    { 
     QMessageBox::information(this, 
           tr("No Results Found"), 
           tr("No results were found for \"%1\"").arg(SearchTerm)); 
     return; 
    } 

    //STEP 6: If results, update model, show first result. 
    Model->setQuery(SearchQuery); 

    QModelIndex index = Model->index(0,1); 
    DisplayContact(index); 
    ui->listView->scrollTo(index); 

    SetView(Contacts::View_DisplaySearchResultsView); 
} 

拆卸觸點

void Contacts::RemoveContact() 
{ 
    if(SelectedRecordId!=-1) 
    { 
     if(QMessageBox::information(this, 
           "Confirm Removal", 
           "Are you sure you want to remove this contact from your list?", 
           QMessageBox::Yes|QMessageBox::No)==QMessageBox::No) 
      return; 

     QSqlQuery DeleteQuery; 
     DeleteQuery.prepare("DELETE FROM Contacts WHERE Id = :i;"); 
     DeleteQuery.bindValue(":i",SelectedRecordId); 


     if(!DeleteQuery.exec()) 
     { 
      qDebug()<<DeleteQuery.lastError().text(); 
      QMessageBox::warning(this, 
           tr("Error Removing Contact"), 
           tr("An error occured while trying to remove this contact.")); 
     }else 
     { 
      SelectedRecordId =-1; 

      clear(); 
      SetView(Contacts::View_AddContactView); 
      Model->setQuery(ActiveQuery); 
      UpdateContactCount(); 
     } 
    }else 
     QMessageBox::warning(this, 
           tr("No Record Selected"), 
           tr("Unexpected Error: Remove Contact Operation is being attempted while no contact is selected.")); 
} 

我真的很感激任何幫助。謝謝:)

回答

0

奇怪的是,代碼工作消除這行代碼後罰款:

ui->listView->scrollTo(index); 
+0

會保持這一行並添加'fetchMore()'幫助嗎?我真的很想搞清楚爲什麼它不起作用。 「scrollTo」這行可能只是暴露了一個問題 - 它的移除論文是我認爲的潛在問題。你應該可以做到沒有問題的滾動。 –

3

唯一想到的是需要確保查詢的所有結果都被提取。一個開放的查詢可能會保持數據庫鎖定。也許。因此

年初STEP6的看起來像以下:

//STEP 6: If results, update model, show first result. 
Model->setQuery(SearchQuery); 
while (Model->canFetchMore()) { 
    Model->fetchMore(); 
} 

不傷害嘗試,我猜。