2012-06-08 125 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(); 
} 

不伤害尝试,我猜。