Utilice ADO para la programación de bases de datos en Visual C
1. Genere el marco de la aplicación e inicialice el entorno de la biblioteca OLE/COM
Cree una aplicación MFC AppWizard (exe) estándar y luego inicialice OLE en la función InitInstance utilizando la base de datos ADO. Biblioteca /COM (porque la biblioteca ADO es una biblioteca COM DLL).
Este ejemplo es:
BOOL CAdotestDlg::OnInitDialog()
{
}
En el final del programa Para llamar:: CoUninitialize(); // Libera los recursos COM ocupados por el programa.
Además:
m_pRecordset-Close(); ¡Atención! ! ! ¡No cierres varias veces! ! ! ! ! ! ! ! ! ! ! !
m_pConnection-Close();
m_pRecordset = NULL;
m_pConnection = NULL
2. p>
p>
Antes de usar ADO, debe usar el símbolo de importación directa #import al final del archivo stdafx.h del proyecto para introducir el archivo de la biblioteca ADO para que el compilador pueda compilarlo correctamente. El código es el siguiente:
#import "C:Program Filescommon filessystemadomsado15.dll" no_namespace rename ("EOF", "adoEOF")
Se almacena la definición de la clase ADO como recurso en ADO DLL (msado15.dll) se denomina biblioteca de tipos internamente. La biblioteca de tipos describe la interfaz autónoma, así como la interfaz COM vtable utilizada por C. Cuando se utiliza la directiva #import, Visual C necesita leer esta biblioteca de tipos desde ADO DLL en tiempo de ejecución y crear un conjunto de archivos de encabezado C. Estos archivos de encabezado tienen. tli y. Con la extensión, los lectores pueden encontrar estos dos archivos en el directorio del proyecto. Las clases ADO llamadas desde el código del programa C se definen en estos archivos.
La tercera línea del programa indica al objeto ADO que no utilice espacios de nombres. En algunas aplicaciones, es necesario utilizar espacios de nombres porque pueden producirse conflictos de nombres entre los objetos de la aplicación y los objetos de ADO. Si desea utilizar un espacio de nombres, puede modificar la tercera línea del programa para: rename_namespace ("AdoNS"). La cuarta línea de código cambia el nombre de EOF (Fin de archivo) en ADO a adoEOF para evitar conflictos con otras bibliotecas que definen su propio EOF.
3. Utilice punteros inteligentes para operaciones de bases de datos
Defina dos instancias de clase de puntero inteligente ADO en el archivo de encabezado CaboutDlg y agregue un ListCtrl en el cuadro de diálogo.
clase CAdotestDlg: CDialog público
{
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset;
ClistCtrl m_List;
}
La biblioteca ADO contiene tres punteros inteligentes: _ConnectionPtr, _CommandPtr y _RecordsetPtr.
_ConnectionPtr se usa generalmente para crear una conexión de datos o ejecutar un SQL que no devuelve ningún resultado. declaración, como un procedimiento almacenado.
_CommandPtr devuelve un conjunto de registros.
Proporciona una manera sencilla de ejecutar procedimientos almacenados y declaraciones SQL que devuelven conjuntos de registros. Cuando utilice la interfaz _CommandPtr, puede utilizar la interfaz global _ConnectionPtr o puede utilizar la cadena de conexión directamente en la interfaz _CommandPtr. _RecordsetPtr es un objeto de conjunto de registros. En comparación con los dos objetos anteriores, proporciona más funciones de control para el conjunto de registros, como bloqueo de registros, control del cursor, etc.
Agregue el siguiente código a OnButton1 en la respuesta del evento usando el programa ADO:
void CAdotestDlg::OnButton1()
{
m_List .ResetContent();
m_pConnection.CreateInstance(_uuidof(Connection)); //Inicializar puntero de conexión
m_pRecordset.CreateInstance(_uuidof(Recordset)); //Inicializar conjunto de registros pointer
try
{
m_pConnection-Open("DSN=ADOTest","","",0 //Conecta los datos ODBC llamados); ADOTest Source
//Nota: Esta es la función abierta que no requiere una identificación de usuario o contraseña para conectarse
// De lo contrario, el formulario es -Open("DSN=test; uid=sa;pwd= 123;","","",0);
//Ejecute la instrucción SQL para obtener un conjunto de registros y asignar su puntero a m_pRecordset
CString strSql="seleccione * desde el medio ";
BSTR bstrSQL = strSql.AllocSysString();
m_pRecordset-Open(bstrSQL, (IDispatch*)m_pConnection, adOpenDynamic, adLockOptimistic, p>
adCmdText) ;
//adOpenDynamic: adLockOptimistic dinámico método de bloqueo optimista adCmdText: declaración de consulta de texto
while (!m_pRecordset-adoEOF) //Atravesar todos los registros p>
{
//Una de las formas de obtener el valor del campo de registro
_variant_t TheValue; //Tipo de datos VARIANT
TheValue = m_pRecordset -GetCollect("BIG_NAME"); // Obtiene el valor del campo BIG_NAME
if (TheValue.vt!=VT_NULL)
m_List.AddString ((char*)_bstr_t(TheValue ));
/ /Agregar el valor al control de lista
//La segunda forma de obtener el valor del campo de registro
// _bstr_t TheValue1=m_pRecordset -Fields-GetItem("BIG_NAME")-Value
//CString temp=TheValue1.copy();
// m_List.AddString(temp);
//Conversión de tipo de datos
_variant_t vUsername, vBirthday, vID, vOld;
TRACE("id: d, nombre: s, edad: d, cumpleaños: s" ,
vID.lVal, (LPCTSTR) (_bstr_t) vUsername, vOld.lVal, (LPCTSTR) (_bstr_t) vCumpleaños);
m_pRecordset-MoveNext()
;//Ir al siguiente registro
}
m_pRecordset-Close();
m_pConnection-Close();
}
catch (_com_error e) //Manejo de excepciones
{
AfxMessageBox(e.ErrorMessage());
} p>
m_pRecordset-Close(); //¡Atención! ! ! ¡No cierres varias veces! ! ! ! De lo contrario, se producirá un error
m_pConnection-Close();
m_pRecordset = NULL;
m_pConnection = NULL;
}
En el programa, los objetos COM y los datos de tipo C se convierten a través de _variant_t y _bstr_t. La clase _variant_t encapsula el tipo de datos VARIANT autónomo OLE. Es mucho más fácil usar la clase _variant_t en C que usar el tipo de datos VARIANT directamente.
Está bien, el programa se puede ejecutar después de la compilación, pero recuerde crear una fuente de datos ODBC llamada ADOTest antes de ejecutarlo. Este programa mostrará el valor del campo BIG_NAME en la tabla del medio en el control de lista.
4. Ejecute el comando SQL y obtenga el conjunto de registros de resultados
Para obtener el conjunto de registros de resultados, definimos un puntero al objeto Recordset: _RecordsetPtr m_pRecordset;
Y cree una instancia del objeto Recordset para él: m_pRecordset.CreateInstance("ADODB.Recordset");
La ejecución de comandos SQL puede tomar muchas formas, que explicaremos a continuación.
(1) Utilice el método Execute del objeto Connection para ejecutar comandos SQL
El prototipo del método Execute es el siguiente:
_RecordsetPtr Connection15:: Ejecutar (_bstr_t CommandText, VARIANT * RecordsAffected,
Opciones largas)
Donde CommandText es la cadena de comando, generalmente un comando SQL.
El parámetro RecordsAffected es el número de filas afectadas después de que se completa la operación.
El parámetro Opciones indica el tipo de contenido en CommandText. Las opciones pueden tomar uno de los siguientes valores: <. /p>
adCmdText: Indica que CommandText es un comando de texto
adCmdTable: Indica que CommandText es un nombre de tabla
adCmdProc: Indica que CommandText es un procedimiento almacenado
adCmdUnknown: Desconocido
Después de ejecutar Execute, devuelve un puntero al conjunto de registros. A continuación damos el código específico y la explicación.
_variant_t RecordsAffected;
///Ejecute el comando SQL: CREATE TABLE para crear la tabla de usuarios que contiene cuatro campos: ID entero, nombre de usuario de cadena,
m_pConnection-Execute ("CREATE TABLE usuarios (ID INTEGER, nombre de usuario TEXTO, antiguo INTEGER, cumpleaños
DATETIME)",
RecordsAffected,
adCmdText);
///Agregar registros a la tabla
m_pConnection-Execute("INSERT INTO usuarios (ID, nombre de usuario, antiguo, cumpleaños ) VALUES
(1, ''''Washington'''', 25, ''''1970/1/1'''')", RecordsAffected, adCmdText);
///Agregue uno al valor de campo antiguo de todos los registros
m_pConnection-Execute ("UPDATE usuarios SET antiguo = antiguo 1", RecordsAffected, adCmdText);
/ // Ejecute el comando de estadísticas SQL para obtener un conjunto de registros que contenga el número de registros
m_pRecordset = m_pConnection-Execute ("SELECT COUNT (*) FROM usuarios", RecordsAffected, adCmdText);
_variant_t vIndex = (long) 0;
_variant_t vCount = m_pRecordset-GetCollect(vIndex); ///Obtener el valor del primer campo y ponerlo en la variable vCount
Las dos oraciones anteriores se pueden escribir como: _variant_t vCount = m_pRecordset-GetCollect((_variant_t)((long)0));
m_pRecordset-Close() ///Cerrar el conjunto de registros p>
CString mensaje;
message.Format("***Hay d registros", vCount.lVal);
AfxMessageBox(message); ///Display); el número actual de registros
( 2) Utilice el objeto Command para ejecutar comandos SQL
_CommandPtr m_pCommand;
m_pCommand.CreateInstance("ADODB.Command") ;
_variant_t vNULL;
vNULL.vt = VT_ERROR;
vNULL.scode = DISP_E_PARAMNOTFOUND ///Definido como sin parámetros
m_pCommand-ActiveConnection = m_pConnection; ///Una oración muy crítica, asígnele la conexión establecida
m_pCommand-CommandText = "SELECT * FROM usuarios" ///Cadena de comando
m_pR
ecordset = m_pCommand-Execute(vNULL, vNULL, adCmdText); /// Ejecute el comando y obtenga el conjunto de registros
En este código, solo usamos el objeto Command para ejecutar la instrucción de consulta SELECT y el El objeto de comando se está ejecutando. Su función puede reflejarse verdaderamente en la llamada de procedimientos almacenados. Entraremos en detalles la próxima vez.
(3) Utilice directamente el objeto Recordset para consultar y obtener el conjunto de registros
Instancia--
void CGmsaDlg::OnDBSelect()
{
// TODO: agregue aquí el código del controlador de notificaciones de control
_RecordsetPtr Rs1; //Defina el objeto Recordset
_bstr_t Connect("DSN= GMS; UID =sa;PWD=;"); //Definir la cadena de conexión
_bstr_t Source ("SELECT count (*) FROM buaa.mdb010"); //Instrucción SQL a ejecutar p>
HRESUL hr = Rs1.CreateInstance(__uuidof(Recordset));
//Omitir el juicio del valor de retorno hr
Rs1-Open(Source, p>
Conectar,
adOpenForwardOnly,
adLockReadOnly,
-1
_variant_t temp=Rs1-GetCollect( _variant_t((long )0));
CString strTemp=(char*)(_bstr_t)temp;
MessageBox("OK!" strTemp);
}
}
p>Por ejemplo
m_pRecordset-Open("SELECT * FROM usuarios",
_variant_t((IDispatch *)m_pConnection, true),
adOpenStatic ,
adLockOptimistic,
adCmdText);
El prototipo del método Open es como esto:
HRESULT Recordset15::Open (const _variant_t
Fuente,
const _variant_t
ActiveConnection,
enum CursorTypeEnum CursorType,
enum LockTypeEnum LockType,
opciones largas)
Entre ellos:
①La fuente es la cadena de consulta de datos
②ActiveConnection es la conexión establecida (necesitamos usar el puntero del objeto de conexión para construir un objeto _variant_t)
③CursorType tipo de cursor, que puede ser uno de los siguientes valores, consulte esta estructura de enumeración :
enum CursorTypeEnum
{
adOpenUnspecified = -1, ///Sin especificación especial
adOpenForwardOnly = 0, /// Avance el cursor estático. Este tipo de cursor solo puede explorar el registro establecido hacia adelante, como usar MoveNext para desplazarse hacia adelante. Este método puede aumentar la velocidad de navegación.
Sin embargo, BookMark, RecordCount, AbsolutePosition y AbsolutePage no se pueden usar
adOpenKeyset = 1, /// El conjunto de registros que usa este cursor no puede ver las operaciones de adición y eliminación de otros usuarios, sino para actualizar el Grabado original operaciones
son visibles para usted.
adOpenDynamic = 2, /// Cursor dinámico. Todas las operaciones de la base de datos se reflejan inmediatamente en cada conjunto de registros de usuario.
adOpenStatic = 3 ///Cursor estático. Genera una copia de seguridad estática para su conjunto de registros, pero las operaciones de adición, eliminación y actualización de otros usuarios son invisibles para su conjunto de registros.
};
④Tipo de bloqueo LockType, puede ser uno de los siguientes valores; consulte la siguiente estructura de enumeración:
enum LockTypeEnum
{
adLockUnspecified = -1, ///Sin especificar
adLockReadOnly = 1, ///Conjunto de registros de solo lectura
adLockPessimistic = 2, bloqueo pesimista Forma. Los datos bloquean todas las demás acciones durante la actualización. Este es el mecanismo de bloqueo más seguro
adLockOptimistic = 3, método de bloqueo optimista. El registro solo se bloquea cuando llama al método Actualizar. Antes de esto, aún puede realizar operaciones como actualizar, insertar y eliminar datos
adLockBatchOptimistic = 4, actualización por lotes optimista. Los registros no se bloquean durante la edición y los cambios, inserciones y eliminaciones se completan en modo por lotes
.
};
⑤Las opciones pueden tomar uno de los siguientes valores:
adCmdText: Indica que CommandText es un comando de texto
adCmdTable: Indica que CommandText es un nombre de tabla
adCmdProc: Indica que CommandText es un procedimiento almacenado
adCmdUnknown: Desconocido
Recorrido y actualización de conjuntos de registros
p>
Según la tabla de usuarios que acabamos de crear ejecutando el comando SQL, contiene cuatro campos: ID, nombre de usuario, antiguo, fecha de nacimiento
La siguiente implementación de código: abra el conjunto de registros, recorra todos registros y elimine el primer registro, agregue tres registros, mueva el cursor al segundo registro,
cambie su edad y guárdelo en la base de datos.
_variant_t vUsername, vBirthday, vID, vOld;
_RecordsetPtr m_pRecordset
m_pRecordset.CreateInstance("ADODB.Recordset"); >m_pRecordset-Open("SELECT * FROM usuarios",
_variant_t((IDispatch*)m_pConnection, true),
adOpenStatic,
adLockOptimistic, p>
p>
adCmdText);
while(!m_pRecordset-adoEOF)
{
vID = m_pRecordset-GetCollect(_variant_t( (long)0) ); ///Obtiene el valor de la columna 1, contando desde 0,
///También puedes dar directamente el nombre de la columna, como en la siguiente línea
vUsername = m_pRecordset- GetCollect("username"); ///Obtener el valor del campo de nombre de usuario
vOld = m_pRecordset-GetCollect("old");
vBirthday = m_pRecordset-GetCollect("cumpleaños") ;
///Envíe los registros en el conjunto de registros en la ventana SALIDA en modo DEPURACIÓN
if (vID.vt! = VT_NULL
vUsername.vt != VT_NULL
vOld.vt != VT_NULL
vCumpleaños.vt
!= VT_NULL)
TRACE("id: d, nombre: s, edad: d, cumpleaños: s",
vID.lVal,
(LPCTSTR) (_bstr_t) vUsername,
vOld.lVal,
(LPCTSTR)(_bstr_t)vBirthday);
m_pRecordset-MoveNext() ///Pasar al siguiente registro; p>
}
m_pRecordset-MoveFirst(); ///Mover al primer registro
m_pRecordset-Delete(adAffectCurrent); ///Eliminar el registro actual
p>///Agregue tres nuevos registros y Asignación
for (int i=0; i3; i )
{
m_pRecordset-AddNew (); ///Agregar nuevo registro
m_pRecordset-PutCollect("ID",_variant_t((long)(i 10)));
m_pRecordset-PutCollect("nombre de usuario" , _variant_t("Yelchin"));
m_pRecordset-PutCollect("old",_variant_t((long)71));
m_pRecordset-PutCollect("cumpleaños", _variant_t( "1930-3-15"));
}
>
m_pRecordset-Move(1,_variant_t((long)adBookmarkFirst)); /// Mover un registro hacia abajo desde el primer registro, es decir, mover
al segundo registro
p>m_pRecordset-PutCollect(_variant_t("old"), _variant_t((long)45)); ///Modificar su antigüedad
m_pRecordset-Update() ///Guardar en la biblioteca Medio
Observaciones: para consultas múltiples, el proceso de consulta se puede convertir en una función ExecuteSQL para permitir que m_pRecordset obtenga el puntero de conexión m_pConnection resultado de la consulta
void ExecuteSQL (_ConnectionPtr m_pConnection, _RecordsetPtr m_pRecordset, CString strSql)
{
//Ejecutar sentencia Select
BSTR bstrSQL = strSql.AllocSysString();
probar
{
m_pRecordset-Open(bstrSQL, (IDispatch*)m_pConnection, adOpenDynamic, adLockOptimistic,
adCmdText);
//adOpenDynamic: dinámico adLockOptimistic método de bloqueo optimista adCmdText: declaración de consulta de texto
}
catch (_com_error error)
{
CString errorMessage;
errorMessage.Format("s", (LPTSTR)error.Description());
AfxMessageBox(errorMessage);
}
}
//Manejo de errores:
3127--Tabla de destino no encontrada
3092--La tabla de destino ya existe
Por ejemplo:
catch(const _com_error e)
{
AfxMessageBox(e.Description());
long errorCode=e.WCode ();
p>
if (3127==errorCode) AfxMessageBox ("La tabla no existe");
if (3092==errorCode) AfxMessageBox ("Tabla ya existe");
return FALSE;
}