Red de conocimiento informático - Material del sitio web - Utilice ADO para la programación de bases de datos en Visual C

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,

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

{

//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());

}

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,

Entero antiguo, fecha tipo cumpleaños

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

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

HRESUL hr = Rs1.CreateInstance(__uuidof(Recordset));

//Omitir el juicio del valor de retorno hr

Rs1-Open(Source,

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>

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

}

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;

}