The EX31B example is an "add-change-delete" application that's different from the Access model. The user must explicitly add, update, and delete records. Even if you prefer the Access-style behavior, you can learn a lot about the CRecordView class by going through the steps in the EX31B example.
Here are the steps for building the EX31B example:


When you're finished adding variable names for each edit box, you'll see a screen like the one shown here.
| Menu Command | Command ID | Command Handler | Update Command UI Handler | 
| Add Record | ID_RECORD_ADD | OnRecordAdd | |
| Clear Fields | ID_RECORD_CLEARFIELDS | OnRecordClearfields | |
| Delete Record | ID_RECORD_DELETE | OnRecordDelete | OnUpdateRecordDelete | 
| Update Record | ID_RECORD_UPDATE | OnRecordUpdate | OnUpdateRecordUpdate | 
BOOL CEx31bView::OnMove(UINT nIDMoveCommand) 
{
    switch (nIDMoveCommand)
    {
    case ID_RECORD_PREV:
        m_pSet->MovePrev();
        if (!m_pSet->IsBOF())
            break;
    case ID_RECORD_FIRST:
        m_pSet->MoveFirst();
        break;
    case ID_RECORD_NEXT:
        m_pSet->MoveNext();
        if (!m_pSet->IsEOF())
            break;
        if (!m_pSet->CanScroll()) {
            // Clear screen since we're sitting on EOF
            m_pSet->SetFieldNull(NULL);
            break;
        }
    case ID_RECORD_LAST:
        m_pSet->MoveLast();
        break;
    default:
        // unexpected case value
        ASSERT(FALSE);
    }
    // Show results of Move operation
    UpdateData(FALSE);
    return TRUE;
}
Also, add the declaration for this overridden function to the ex31bView.h header file.
If you have a sorted recordset (or if your ODBC driver doesn't put added records in the recordset), you should call CRecordset::Requery to completely regenerate the recordset. In that case, there's no convenient way to position the cursor on the newly added record, and that's a basic problem with SQL.
Add the following boldface code:
void CEx31bView::OnRecordAdd()
{
    m_pSet->AddNew();
    UpdateData(TRUE);
    if (m_pSet->CanUpdate()) {
        m_pSet->Update();
    }
    if (!m_pSet->IsEOF()) {
        m_pSet->MoveLast();
    }
    m_pSet->Requery(); // for sorted sets
    UpdateData(FALSE);
}
void CEx31bView::OnRecordClearfields() 
{
    m_pSet->SetFieldNull(NULL);
    UpdateData(FALSE);
}
void CEx31bView::OnRecordDelete() 
{
    CRecordsetStatus status;
    try {
        m_pSet->Delete();
    }
    catch(CDBException* e) {
        AfxMessageBox(e->m_strError);
        e->Delete();
        m_pSet->MoveFirst(); // lost our place!
        UpdateData(FALSE);
        return;
    }
    m_pSet->GetStatus(status);
    if (status.m_lCurrentRecord == 0) {
        // We deleted last of 2 records
        m_pSet->MoveFirst();
    }
    else {
        m_pSet->MoveNext();
    }
    UpdateData(FALSE);
}
void CEx31bView::OnUpdateRecordDelete(CCmdUI* pCmdUI) 
{
    pCmdUI->Enable(!m_pSet->IsEOF());
}
void CEx31bView::OnRecordUpdate() 
{
    m_pSet->Edit();
    UpdateData(TRUE);
    if (m_pSet->CanUpdate()) {
        m_pSet->Update();
    }
// should requery if key field changed
}
void CEx31bView::OnUpdateRecordUpdate(CCmdUI* pCmdUI) 
{
    pCmdUI->Enable(!m_pSet->IsEOF());
}