Página inicial | Presentación


AÑADIR UN BUFFER

Estado actual

Cuando se quiera acceder a los datos de una tabla, el IDE de Visual C++ 6.0 permite añadir fácilmente al proyecto una nueva clase de tipo MFC derivada de CRecordset o de CDaoRecordset. Después de haber especificado el origen de los datos y la tabla a considerar, se genera automáticamente una clase que tiene necesidad de definir específicamente un cierto número de variables a usar para la comunicación con la base de datos y con la eventual ventana de visualización. Tal comunicación se realiza por medio de funciones especializadas, definidas adrede por la MFC, las cuales obligan a la nueva clase a conocer el tipo de los campos a los cuales accede.

Mejora introducida

Las clases CBufferRecSet y CBufferDaoRecSet, derivadas de CRecordset y CDaoRecordset respectivamente, han sido pensadas para librarse de las citadas necesidades: estas clases mantienen un buffer dinámico que asocia automáticamente una variable a cada campo del recordset, y además contienen métodos para realizar el intercambio de datos entre la base de datos y el buffer (DoFieldExchange) y entre el buffer y una ventana de visualización (DDX_FieldVariant), encargándose de llamar a las funciones oportunas de la MFC según el tipo de campo en objeto. Asimismo, prevén métodos para el acceso directo a las variables del buffer, bien en lectura, bien en escritura, y permiten definir un filtro sobre el recordset en el momento de realizar el Open, pasando como parámetro el nombre del campo filtrado y el puntero a una variable con el valor al que se refiere (actualmente se prevé el filtro sobre un solo campo). En su implementación se mantiene la compatibilidad respectivamente con las clases CRecordView y CDaoRecordView de la MFC.

Ejemplo

Veamos en los listados mostrados a continuación un ejemplo de la simplificación que se obtiene usando las clases CBufferRecSet y CBufferDaoRecSet en el lugar de las originales CRecordset y CDaoRecordset. A la izquierda se encuentra el código tal y como ha sido generado por el AppWizard, mientras que a la derecha se encuentra el correspondiente código modificado para utilizar las nuevas clases. El significado que se atribuye a los colores es el siguiente:

   código modificado    código quitado    código añadido

DAO

Después de haber creado un nuevo proyecto de tipo MFC AppWizard (exe), con las opciones Single document y Database view with file support (con elección de un Data source de tipo DAO que accediese a la tabla Pedidos de la base de datos de ejemplo de Microsoft Access - Neptuno.mdb), se han añadido en el dialog box generado tantos edit box como campos de la tabla, y después con el ClassWizard se han conectado los edit box a las variables asociadas a los campos.

class CDaoDBSet : public CDaoRecordset
{
public:
   CDaoDBSet(CDaoDatabase* pDatabase = NULL);
   DECLARE_DYNAMIC(CDaoDBSet)

// Field/Param Data
//{{AFX_FIELD(CDaoDBSet, CDaoRecordset)
   long m_IdPedido;
   CString m_IdCliente;
   long m_IdEmpleado;
   COleDateTime m_FechaPedido;
   COleDateTime m_FechaEntrega;
   COleDateTime m_FechaEnv_o;
   long m_FormaEnv_o;
   COleCurrency m_Cargo;
   CString m_Destinatario;
   CString m_Direcci_nDestinatario;
   CString m_CiudadDestinatario;
   CString m_Regi_nDestinatario;
   CString m_C_dPostalDestinatario;
   CString m_Pa_sDestinatario;
//}}AFX_FIELD

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDaoDBSet)
public:
   virtual CString GetDefaultDBName(); // REVIEW: Get a comment here
   virtual CString GetDefaultSQL(); // default SQL for Recordset
   virtual void DoFieldExchange(CDaoFieldExchange* pFX); // RFX support
//}}AFX_VIRTUAL

// Implementation
#ifdef _DEBUG
   virtual void AssertValid() const;
   virtual void Dump(CDumpContext& dc) const;
#endif
};
class CDaoDBSet : public CBufferDaoRecSet
{
public:
   CDaoDBSet(CDaoDatabase* pDatabase = NULL);
   DECLARE_DYNAMIC(CDaoDBSet)

// Field/Param Data
//{{AFX_FIELD(CDaoDBSet, CBufferDaoRecSet)
//}}AFX_FIELD

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDaoDBSet)
public:
   virtual CString GetDefaultDBName(); // REVIEW: Get a comment here
   virtual CString GetDefaultSQL(); // default SQL for Recordset
//}}AFX_VIRTUAL

// Implementation
#ifdef _DEBUG
   virtual void AssertValid() const;
   virtual void Dump(CDumpContext& dc) const;
#endif
};
CDaoDBSet::CDaoDBSet(CDaoDatabase* pdb)
   : CDaoRecordset(pdb)
{
//{{AFX_FIELD_INIT(CDaoDBSet)
   m_IdPedido = 0;
   m_IdCliente = _T("");
   m_IdEmpleado = 0;
   m_FechaPedido = (DATE)0;
   m_FechaEntrega = (DATE)0;
   m_FechaEnv_o = (DATE)0;
   m_FormaEnv_o = 0;
   m_Destinatario = _T("");
   m_Direcci_nDestinatario = _T("");
   m_CiudadDestinatario = _T("");
   m_Regi_nDestinatario = _T("");
   m_C_dPostalDestinatario = _T("");
   m_Pa_sDestinatario = _T("");
   m_nFields = 14;
//}}AFX_FIELD_INIT
   m_nDefaultType = dbOpenDynaset;
}
CDaoDBSet::CDaoDBSet(CDaoDatabase* pdb)
   : CBufferDaoRecSet(pdb)
{
//{{AFX_FIELD_INIT(CDaoDBSet)
//}}AFX_FIELD_INIT
   m_nDefaultType = dbOpenDynaset;
}
void CDaoDBSet::DoFieldExchange(CDaoFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CDaoDBSet)
   pFX->SetFieldType(CDaoFieldExchange::outputColumn);
   DFX_Long(pFX, _T("[IdPedido]"), m_IdPedido);
   DFX_Text(pFX, _T("[IdCliente]"), m_IdCliente);
   DFX_Long(pFX, _T("[IdEmpleado]"), m_IdEmpleado);
   DFX_DateTime(pFX, _T("[FechaPedido]"), m_FechaPedido);
   DFX_DateTime(pFX, _T("[FechaEntrega]"), m_FechaEntrega);
   DFX_DateTime(pFX, _T("[FechaEnvío]"), m_FechaEnv_o);
   DFX_Long(pFX, _T("[FormaEnvío]"), m_FormaEnv_o);
   DFX_Currency(pFX, _T("[Cargo]"), m_Cargo);
   DFX_Text(pFX, _T("[Destinatario]"), m_Destinatario);
   DFX_Text(pFX, _T("[DirecciónDestinatario]"), m_Direcci_nDestinatario);
   DFX_Text(pFX, _T("[CiudadDestinatario]"), m_CiudadDestinatario);
   DFX_Text(pFX, _T("[RegiónDestinatario]"), m_Regi_nDestinatario);
   DFX_Text(pFX, _T("[CódPostalDestinatario]"), m_C_dPostalDestinatario);
   DFX_Text(pFX, _T("[PaísDestinatario]"), m_Pa_sDestinatario);
//}}AFX_FIELD_MAP
}
 
void CDaoDBView::DoDataExchange(CDataExchange* pDX)
{
  CDaoRecordView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDaoDBView)
   DDX_FieldText(pDX, IDC_EDIT1, m_pSet->m_IdPedido, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT2, m_pSet->m_IdCliente, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT3, m_pSet->m_IdEmpleado, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT4, m_pSet->m_FechaPedido, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT5, m_pSet->m_FechaEntrega, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT6, m_pSet->m_FechaEnv_o, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT7, m_pSet->m_FormaEnv_o, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT8, m_pSet->m_Cargo, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT9, m_pSet->m_Destinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT10, m_pSet->m_Direcci_nDestinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT11, m_pSet->m_CiudadDestinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT12, m_pSet->m_Regi_nDestinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT13, m_pSet->m_C_dPostalDestinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT14, m_pSet->m_Pa_sDestinatario, m_pSet);
//}}AFX_DATA_MAP
}
void CDaoDBView::DoDataExchange(CDataExchange* pDX)
{
  CDaoRecordView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDaoDBView)
//}}AFX_DATA_MAP

   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT1, 0); // IdPedido
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT2, 1); // IdCliente
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT3, 2); // IdEmpleado
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT4, 3); // FechaPedido
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT5, 4); // FechaEntrega
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT6, 5); // FechaEnvío
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT7, 6); // FormaEnvío
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT8, 7); // Cargo
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT9, 8); // Destinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT10, 9); // DirecciónDestinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT11, 10); // CiudadDestinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT12, 11); // RegiónDestinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT13, 12); // CódPostalDestinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT14, 13); // PaísDestinatario
}

ODBC

Después de haber creado un nuevo proyecto de tipo MFC AppWizard (exe), con las opciones Single document y Database view with file support (con elección de un Data source de tipo ODBC que accediese a la tabla Pedidos de la base de datos de ejemplo de Microsoft Access - Neptuno.mdb), se han añadido en el dialog box generado tantos edit box como campos de la tabla, y después con el ClassWizard se han conectado los edit box a las variables asociadas a los campos.

class CODBCDBSet : public CRecordset
{
public:
   CODBCDBSet(CDatabase* pDatabase = NULL);
   DECLARE_DYNAMIC(CODBCDBSet)

// Field/Param Data
//{{AFX_FIELD(CODBCDBSet, CRecordset)
   long m_IdPedido;
   CString m_IdCliente;
   long m_IdEmpleado;
   CTime m_FechaPedido;
   CTime m_FechaPedido;
   CTime m_FechaEntrega;
   CTime m_FechaEnv_o;
   long m_FormaEnv_o;
   CString m_Cargo;
   CString m_Destinatario;
   CString m_Direcci_nDestinatario;
   CString m_CiudadDestinatario;
   CString m_Regi_nDestinatario;
   CString m_C_dPostalDestinatario;
   CString m_Pa_sDestinatario;
//}}AFX_FIELD

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CODBCDBSet)
public:
   virtual CString GetDefaultConnect(); // Default connection string
   virtual CString GetDefaultSQL(); // default SQL for Recordset
   virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support
//}}AFX_VIRTUAL

// Implementation
#ifdef _DEBUG
   virtual void AssertValid() const;
   virtual void Dump(CDumpContext& dc) const;
#endif
};
class CODBCDBSet : public CBufferRecSet
{
public:
   CODBCDBSet(CDatabase* pDatabase = NULL);
   DECLARE_DYNAMIC(CODBCDBSet)

// Field/Param Data
//{{AFX_FIELD(CODBCDBSet, CBufferRecSet)
//}}AFX_FIELD

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CODBCDBSet)
public:
   virtual CString GetDefaultConnect(); // Default connection string
   virtual CString GetDefaultSQL(); // default SQL for Recordset
//}}AFX_VIRTUAL

// Implementation
#ifdef _DEBUG
   virtual void AssertValid() const;
   virtual void Dump(CDumpContext& dc) const;
#endif
};
CODBCDBSet::CODBCDBSet(CDatabase* pdb)
   : CRecordset(pdb)
{
//{{AFX_FIELD_INIT(CODBCDBSet)
   m_IdPedido = 0;
   m_IdCliente = _T("");
   m_IdEmpleado = 0;
   m_FechaPedido = 0;
   m_FechaEntrega = 0;
   m_FechaEnv_o = 0;
   m_FormaEnv_o = 0;
   m_Cargo = _T("");
   m_Destinatario = _T("");
   m_Direcci_nDestinatario = _T("");
   m_CiudadDestinatario = _T("");
   m_Regi_nDestinatario = _T("");
   m_C_dPostalDestinatario = _T("");
   m_Pa_sDestinatario = _T("");
   m_nFields = 14;
//}}AFX_FIELD_INIT
   m_nDefaultType = snapshot;
}
CODBCDBSet::CODBCDBSet(CDatabase* pdb)
   : CBufferRecSet(pdb)
{
//{{AFX_FIELD_INIT(CODBCDBSet)
//}}AFX_FIELD_INIT
   m_nDefaultType = snapshot;
}
void CODBCDBSet::DoFieldExchange(CFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CODBCDBSet)
   pFX->SetFieldType(CFieldExchange::outputColumn);
   RFX_Long(pFX, _T("[IdPedido]"), m_IdPedido);
   RFX_Text(pFX, _T("[IdCliente]"), m_IdCliente);
   RFX_Long(pFX, _T("[IdEmpleado]"), m_IdEmpleado);
   RFX_Date(pFX, _T("[FechaPedido]"), m_FechaPedido);
   RFX_Date(pFX, _T("[FechaEntrega]"), m_FechaEntrega);
   RFX_Date(pFX, _T("[FechaEnvío]"), m_FechaEnv_o);
   RFX_Long(pFX, _T("[FormaEnvío]"), m_FormaEnv_o);
   RFX_Text(pFX, _T("[Cargo]"), m_Cargo);
   RFX_Text(pFX, _T("[Destinatario]"), m_Destinatario);
   RFX_Text(pFX, _T("[DirecciónDestinatario]"), m_Direcci_nDestinatario);
   RFX_Text(pFX, _T("[CiudadDestinatario]"), m_CiudadDestinatario);
   RFX_Text(pFX, _T("[RegiónDestinatario]"), m_Regi_nDestinatario);
   RFX_Text(pFX, _T("[CódPostalDestinatario]"), m_C_dPostalDestinatario);
   RFX_Text(pFX, _T("[PaísDestinatario]"), m_Pa_sDestinatario);
//}}AFX_FIELD_MAP
}
 
void CODBCDBView::DoDataExchange(CDataExchange* pDX)
{
   CRecordView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CODBCDBView)
   DDX_FieldText(pDX, IDC_EDIT1, m_pSet->m_IdPedido, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT2, m_pSet->m_IdCliente, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT3, m_pSet->m_IdEmpleado, m_pSet);

// no se pueden añadir los siguientes, porque el tipo CTime no tiene soporte
// DDX_FieldText(pDX, IDC_EDIT4, m_pSet->m_FechaPedido, m_pSet);
// DDX_FieldText(pDX, IDC_EDIT5, m_pSet->m_FechaEntrega, m_pSet);
// DDX_FieldText(pDX, IDC_EDIT6, m_pSet->m_FechaEnv_o, m_pSet);

   DDX_FieldText(pDX, IDC_EDIT7, m_pSet->m_FormaEnv_o, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT8, m_pSet->m_Cargo, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT9, m_pSet->m_Destinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT10, m_pSet->m_Direcci_nDestinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT11, m_pSet->m_CiudadDestinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT12, m_pSet->m_Regi_nDestinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT13, m_pSet->m_C_dPostalDestinatario, m_pSet);
   DDX_FieldText(pDX, IDC_EDIT14, m_pSet->m_Pa_sDestinatario, m_pSet);
//}}AFX_DATA_MAP
}
void CODBCDBView::DoDataExchange(CDataExchange* pDX)
{
   CRecordView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CODBCDBView)
//}}AFX_DATA_MAP

   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT1, 0); // IdPedido
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT2, 1); // IdCliente
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT3, 2); // IdEmpleado
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT4, 3); // FechaPedido
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT5, 4); // FechaEntrega
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT6, 5); // FechaEnvío
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT7, 6); // FormaEnvío
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT8, 7); // Cargo
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT9, 8); // Destinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT10, 9); // DirecciónDestinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT11, 10); // CiudadDestinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT12, 11); // RegiónDestinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT13, 12); // CódPostalDestinatario
   m_pSet->DDX_FieldVariant(pDX, IDC_EDIT14, 13); // PaísDestinatario
}

Página inicial | Presentación

1