Compartir a través de


TN053: Personalizar las rutinas DFX para las clases de base de datos DAO

Nota:

DAO se usa con bases de datos de Access y es compatible con Office 2013. DAO 3.6 es la versión final y se considera obsoleta. El entorno y los asistentes de Visual C++ no admiten DAO (aunque se incluyen las clases DAO y todavía se pueden usar). Microsoft recomienda usar plantillas OLE DB o bien ODBC y MFC para proyectos nuevos. Solo debe usar DAO para mantener las aplicaciones existentes.

En esta nota técnica, se describe el mecanismo de intercambio de campos de registros DAO (DFX). Para ayudar a comprender lo que sucede en las rutinas DFX, se explicará con detalle la función DFX_Text como ejemplo. Como fuente adicional de información de esta nota técnica, puede examinar el código de las demás funciones DFX individuales. Probablemente no necesitará una rutina DFX personalizada con tanta frecuencia como sea posible que necesite una rutina RFX personalizada (usada con clases de base de datos ODBC).

Esta nota técnica contiene:

Introducción a DFX

El mecanismo de intercambio de campos de registros DAO (DFX) se usa para simplificar el procedimiento de recuperación y actualización de datos al usar la clase CDaoRecordset. El proceso se simplifica mediante miembros de datos de la clase CDaoRecordset. Al derivar de CDaoRecordset, puede agregar miembros de datos a la clase derivada que representa cada campo de una tabla o consulta. Este mecanismo de "enlace estático" es sencillo, pero es posible que no sea el método de recuperación y actualización de datos que se elija para todas las aplicaciones. DFX recupera cada campo enlazado cada vez que se cambia el registro actual. Si está desarrollando una aplicación sensible al rendimiento que no requiere recuperar todos los campos cuando hay cambios, el "enlace dinámico" mediante CDaoRecordset::GetFieldValue y CDaoRecordset::SetFieldValue puede ser el método de acceso a datos que prefiera.

Nota:

DFX y el enlace dinámico no son mutuamente excluyentes, por lo que se puede utilizar un uso híbrido del enlace estático y dinámico.

Ejemplo 1: uso solo del intercambio de campos de registro DAO

(se supone que el elemento CMySet de la clase derivada de CDaoRecordset ya está abierto)

// Add a new record to the customers table
myset.AddNew();

myset.m_strCustID = _T("MSFT");

myset.m_strCustName = _T("Microsoft");

myset.Update();

Ejemplo 2: uso solo del enlace dinámico

(se supone que se usa la clase CDaoRecordset y que rs ya está abierto)

// Add a new record to the customers table
COleVariant  varFieldValue1 (_T("MSFT"),
    VT_BSTRT);

//Note: VT_BSTRT flags string type as ANSI,
    instead of UNICODE default
COleVariant  varFieldValue2  (_T("Microsoft"),
    VT_BSTRT);

rs.AddNew();

rs.SetFieldValue(_T("Customer_ID"),
    varFieldValue1);

rs.SetFieldValue(_T("Customer_Name"),
    varFieldValue2);

rs.Update();

Ejemplo 3: uso del intercambio de campos de registros DAO y el enlace dinámico

(se supone que se examinan los datos de los empleados emp con la clase derivada de CDaoRecordset)

// Get the employee's data so that it can be displayed
emp.MoveNext();

// If user wants to see employee's photograph,
// fetch it
COleVariant varPhoto;
if (bSeePicture)
    emp.GetFieldValue(_T("photo"),
    varPhoto);

// Display the data
PopUpEmployeeData(emp.m_strFirstName,
    emp.m_strLastName,
    varPhoto);

Funcionamiento de DFX

El mecanismo de DFX funciona de forma similar al mecanismo de intercambio de campos de registros (RFX) utilizado por las clases ODBC de MFC. Los principios de DFX y RFX son los mismos, pero hay numerosas diferencias internas. El diseño de las funciones DFX era de modo que prácticamente todo el código se comparte con las rutinas DFX individuales. En el nivel más alto, DFX solo hace algunas cosas.

  • DFX construye la cláusula SELECT y la cláusula PARAMETERS de SQL si es necesario.

  • DFX construye la estructura de enlace usada por la función GetRows de DAO (más información sobre esto más adelante).

  • DFX administra el búfer de datos usado para detectar campos modificados (si se usa el almacenamiento en búfer doble)

  • DFX administra las matrices de estado NULL y DIRTY y establece los valores si es necesario en las actualizaciones.

En el corazón del mecanismo de DFX, se encuentra la función DoFieldExchange de la clase derivada de CDaoRecordset. Esta función envía las llamadas a las funciones DFX individuales de un tipo de operación adecuado. Antes de llamar a DoFieldExchange, las funciones internas de MFC establecen el tipo de operación. En la lista siguiente, se muestran los distintos tipos de operación y una breve descripción.

Operación Descripción
AddToParameterList Crea la cláusula PARAMETERS.
AddToSelectList Crea la cláusula SELECT.
BindField Configura la estructura del enlace.
BindParam Establece los valores de los parámetros.
Fixup Establece el estado NULL.
AllocCache Asigna la memoria caché para la comprobación de modificaciones.
StoreField Guarda el registro actual en la memoria caché.
LoadField Restaura la memoria caché en los valores de los miembros.
FreeCache Libera la memoria caché.
SetFieldNull Establece el estado y el valor del campo en NULL.
MarkForAddNew Marca los campos modificados si no son PSEUDO NULL.
MarkForEdit Marca los campos modificados si no coinciden con la memoria caché.
SetDirtyField Establece los valores de campo marcados como con modificaciones.

En la sección siguiente, se explicará cada operación con más detalle para DFX_Text.

La característica más importante que se debe comprender sobre el proceso de intercambio de campos de registros DAO es que usa la función GetRows del objeto CDaoRecordset. La función GetRows de DAO puede funcionar de varias maneras. Esta nota técnica solo describirá GetRows brevemente, ya que está fuera del ámbito de esta nota técnica. La función GetRows de DAO puede funcionar de varias maneras.

  • Puede recuperar varios registros y varios campos de datos a la vez. Esto permite un acceso más rápido a los datos con la complicación de tratar con una estructura de datos grande y los desplazamientos adecuados para cada campo y para cada registro de datos de la estructura. MFC no aprovecha este mecanismo de recuperación de varios registros.

  • Otra manera de trabajar con GetRows es permitir que los programadores especifiquen direcciones de enlace para los datos recuperados de cada campo de un registro de datos.

  • DAO también realizará una "devolución de llamada" al autor de la llamada para las columnas de longitud variable con el fin de permitir que el autor de la llamada asigne memoria. Esta segunda característica tiene la ventaja de minimizar el número de copias de datos, así como permitir el almacenamiento directo de los datos en los miembros de una clase (la clase derivada de CDaoRecordset). Este segundo mecanismo es el método que usa MFC para enlazar a miembros de datos en las clases derivadas de CDaoRecordset.

Qué hace la rutina DFX personalizada

Se desprende de esta explicación que la operación más importante implementada en cualquier función DFX debe ser la capacidad de configurar las estructuras de datos necesarias para llamar correctamente a GetRows. Hay una serie de otras operaciones que una función DFX también debe admitir, pero ninguna tan importante o compleja como preparar correctamente la llamada a GetRows.

El uso de DFX se describe en la documentación en línea. Básicamente, hay dos requisitos. En primer lugar, se deben agregar los miembros a la clase derivada de CDaoRecordset para cada campo y parámetro enlazados. Después de esto, se debe invalidar CDaoRecordset::DoFieldExchange. Tenga en cuenta que el tipo de datos del miembro es importante. Debe coincidir con los datos del campo de la base de datos o al menos ser convertibles a ese tipo. Por ejemplo, un campo numérico de la base de datos, como un entero largo, siempre se puede convertir en texto y enlazarse a un miembro CString, pero un campo de texto de una base de datos puede no convertirse necesariamente en una representación numérica, como un entero largo y enlazarse a un miembro de tipo entero largo. DAO y el motor de base de datos Microsoft Jet son responsables de la conversión (en lugar de MFC).

Detalles de DFX_Text

Como se mencionó anteriormente, la mejor manera de explicar cómo funciona DFX es trabajar con un ejemplo. Para este propósito, los aspectos internos de DFX_Text deben funcionar bastante bien para ayudar a proporcionar al menos un conocimiento básico de DFX.

  • AddToParameterList

    Esta operación crea la cláusula PARAMETERS de SQL ("Parameters <param name>, <param type> ... ;") requerida por Jet. Cada parámetro tiene un nombre y un tipo (como se especifica en la llamada a RFX). Consulte la función CDaoFieldExchange::AppendParamType para ver los nombres de los tipos individuales. En el caso de DFX_Text, el tipo utilizado es text.

  • AddToSelectList

    Crea la cláusula SELECT de SQL. Esto es bastante directo, ya que simplemente se anexa el nombre de columna especificado por la llamada a DFX ("SELECT <column name>, ...").

  • BindField

    Las más compleja de las operaciones. Como se mencionó anteriormente, aquí es donde se configura la estructura de enlace de DAO utilizada por GetRows. Como puede ver en el código de DFX_Text, los tipos de información de la estructura incluyen el tipo DAO usado (DAO_CHAR o DAO_WCHAR en el caso de DFX_Text). Además, también se configura el tipo de enlace usado. En una sección anterior, se describió brevemente GetRows, solo lo suficiente explicar que el tipo de enlace usado por MFC siempre es el enlace de dirección directo (DAOBINDING_DIRECT). Además, para el enlace de columna de longitud variable (como DFX_Text) se usa el enlace de devolución de llamada para que MFC pueda controlar la asignación de memoria y especificar una dirección de la longitud correcta. Esto significa que MFC siempre puede indicar a DAO "dónde" colocar los datos, lo que permite enlazar directamente a las variables miembro. El resto de la estructura de enlace se rellena con elementos como la dirección de la función de devolución de llamada de asignación de memoria y el tipo de enlace de columna (enlace por nombre de columna).

  • BindParam

    Se trata de una operación sencilla que llama a SetParamValue con el valor de parámetro especificado en el miembro del parámetro.

  • Fixup

    Rellena el estado NULL de cada campo.

  • SetFieldNull

    Esta operación solo marca el estado de cada campo como NULL y establece el valor de la variable miembro en PSEUDO_NULL.

  • SetDirtyField

    Llama a SetFieldValue para cada campo marcado como con modificaciones.

Todas las operaciones restantes solo tratan con el uso de la memoria caché de datos. La memoria caché de datos es un búfer adicional de los datos del registro actual que se usa para simplificar ciertas cosas. Por ejemplo, se pueden detectar automáticamente los campos "con modificaciones". Como se describe en la documentación en línea, se puede desactivar completamente y también en el nivel de campo. La implementación del búfer utiliza un mapa. Este mapa se usa para hacer coincidir las copias asignadas dinámicamente de los datos con la dirección del campo "enlazado" (o miembro de datos derivado de CDaoRecordset).

  • AllocCache

    Asigna dinámicamente el valor del campo almacenado en caché y lo agrega al mapa.

  • FreeCache

    Elimina el valor del campo almacenado en caché y lo quita del mapa.

  • StoreField

    Copia el valor del campo actual en la memoria caché de datos.

  • LoadField

    Copia el valor almacenado en caché en el miembro de campo.

  • MarkForAddNew

    Comprueba si el valor del campo actual no es NULL y lo marca como con modificaciones si es necesario.

  • MarkForEdit

    Compara el valor del campo actual con la memoria caché de datos y lo marca como con modificaciones si es necesario.

Sugerencia

Modele las rutinas DFX personalizadas en las rutinas DFX existentes para los tipos de datos estándar.

Consulte también

Notas técnicas por número
Notas técnicas por categoría