Sei sulla pagina 1di 11

ADO.

NET para novatos


ADO.NET es la tecnologa de acceso a datos que viene en el .NET Framework. Y aunque su nombre proviene de su predecesor (ADO, ActiveX Data Objects), no tiene casi nada en comn con esa tecnologa. De hecho, maneja un paradigma conceptual completamente opuesto. ADO, RDO, DAO y similares manejaban un modelo conectado, es decir, tu ejecutabas un query en la base de datos y declarabas objetos que mantenan un cursor o un apuntador al registro que queras leer. ADO te provea mtodos para navegar hacia enfrente o hacia atrs en el grupo de datos que te regresaba tu query para que pudieras leerlos y/o alterarlos. Todo esto se haca en vivo y en directo sobre la base de datos. Las desventajas de esta tecnologa eran algunas, pero la principal es que necesitas mantener una conexin abierta en todo momento para manipular los datos. As que si tenas, digamos 20 licencias para conectarte a tu base de datos, pues fcilmente podas saturarlas con 20 usuarios que estuvieran utilizando la aplicacin con alguna pantalla abierta, aunque no estuvieran realizando ninguna actividad. Es como cuando tienes un vecino muy platicador y con muy poca vida propia. Llegas tu casa del trabajo y ests metiendo el auto en tu cochera, cuando te lo topas y lo saludas: Qu tal vecino, qu cuentas? Pos fjate que la suegra del primo de la hermana de la vecina wachumaru la gallina blah blah blah blah blah bla (continuando por al menos 30 minutos). Y t ya te quieres meter a tu casa porque te ests cayendo de sueo, pero el maldito vecino no se calla y ya mejor no quieres ni hablar porque sabes que si le haces cualquier otra pregunta o haces la ms mnima muestra de inters en la conversacin vas a estar ah otra hora y l todava est hablando de lo gracioso que se ve su beb recin nacido cuando regurgita y aaaAAARGHHH! Ejem en qu estaba? Ah s! Sin embargo, ADO.NET maneja un modelo desconectado, ms que nada por que el otro no es el ms ptimo en cierto tipo de aplicaciones como las de Web o dispositivos mviles. Es decir, la idea aqu es que te conectes a la base de datos (o cualquier otro almacn de datos), hagas lo que tengas que hacer y te desconectes, liberando lo ms rpido posible recursos de red, licencias, etctera. Puedes mantener si gustas una copia cacheada de los datos en memoria, y luego cuando ests conectado nuevamente simplemente sincronizas tus datos con los del servidorms sobre esto cuando veamos los DataSets. As que en lugar del vecino guacamaya, es como cuando te topas un compa de toda la vida en la calle: Qu rollo, vato? Cero balero. Qu cuentan las morritas? Nada, ah andan todas bien felices. rale. Qu buen pex. Me las saludas nos vemos. (Y ya, tan tan)

DataWhat?
En cuanto comienzas a trabajar con ADO.NET vers un montn de clases con nombres similares: DataReader, DataAdapter, DataSet, DataTable, DataRow, DataRowView, DataCongal bueno ese ltimo quiz no sea real, pero el resto de las clases s existen y debes conocerlas si quieres utilizar tus DataDatos en tu DataAplicacin. Est bueno pues, ya fueron suficientes DataPayasadas. Pero antes de meternos en ese tema, hay otros dos objetos que son ms primitivos y que permiten que te conectes e interactes con una base de datos: Connection y Command.

Connection permite que entables un canal de comunicacin con tu base de datos, y Command permite que ejecutes alguna instruccin sobre el motor de la base de datos, por ejemplo un query SQL de SELECT, INSERT, UPDATE o DELETE, o ejecutar un Stored Procedure.

La clase exacta que utilizars para establecer tu conexin y comandos depender del proveedor de datos que utilices, y el proveedor depender del tipo de base de datos a la que te quieras conectar: SQL Server, Oracle, Access, MySQL, etctera. Y aunque hay una forma en el .NET Framework 2.0 de hacer tu cdigo independiente del proveedor de base de datos, no hay que mezclar el caldo con la sopa todava; lo veremos en otro artculo. Por ahora, si quieres interactuar con una base de datos SQL Server, tendrs que utilizar SqlConnection y SqlCommand; si quieres platicar con Oracle tendrs que usar OracleConnection y OracleCommand; y si quieres hacerlo con Access, puedes usar OleDbConnection y OleDbCommand. Sin importar cul selecciones, los pasos para utilizarlo siempre son los mismos: 1. Abres la conexin 2. Haces tu desmadre (o sea, ejecutas tus comandos) 3. Cierras la conexin Usando SQL Server sera algo como esto:
// asumiendo que al principio se declar // using System.Data.SqlClient; // para usar ms fcilmente clases del SQL Server Data Provider SqlConnection miConexion = new SqlConnection("MiStringDeConexion"); miConexion.Open(); // Hago mis cosas miConexion.Close();

La conexin requerir de un string de conexin, de acuerdo al proveedor de datos, para indicar a qu base de datos conectarse y con qu credenciales. Por ahora utilizar "MiStringDeConexin" para mostrar donde va ese valor. Una prctica muy recomendada para evitar que se nos olvide cerrar la conexin es utilizar la instruccin using de C# (VB 2005 tambin la tiene). Ojo: No es la misma que la que se utiliza para importar un espacio de nombres.
using (SqlConnection miConexion = new SqlConnection("MiStringDeConexion")) {

miConexion.Open(); // Hago mis cosas // using, automticamente invoca los finalizadores, Close() en este caso, // en cuanto se termina el scope de la instruccin. }

El comando en s se especifica utilizando la propiedad CommandText. Adems, puedes especificar el tipo del comando que ests ejecutando con la propiedad CommandType:

TextCualquier query, incuyendo comandos para manipular la base de datos (CREATE TABLE, DROP TABLE, etc.) StoredProcedurePara ejecutar un procedimiento almacenado. TableDirectPara leer una tabla completita. Este no es soportado por algunos proveedores de datos como el de SQL Server.
using (SqlConnection miConexion = new SqlConnection("MiStringDeConexion")) { miConexion.Open(); // // hago mis cosas: // SqlCommand cmd1 = new SqlCommand(); cmd1.Connection = miConexion; cmd1.CommandType = System.Data.CommandType.Text; cmd1.CommandText = "SELECT * FROM 'Peliculas'"; // no lo estamos ejecutando todavia SqlCommand cmd2 = new SqlCommand(); cmd2.Connection = miConexion; cmd2.CommandType = System.Data.CommandType.StoredProcedure; cmd2.CommandText = "SelectPeliculas"; // nombre de mi SP en mi DB // falta ejecutarlo } // using manda llamar miConexion.Close()

Para ejecutar tus instrucciones, la clase Command te da 3 mtodos principales:


ExecuteNonQuery()Para cuando tu instruccin no regresa una respuesta, p. ej. un INSERT, UPDATE o DELETE ExecuteScalar()Para cuando tu instruccin regresa UN SOLO registro con UN SOLO campo con un valor numrico, por ejemplo el resultado de un SELECT COUNT(*) FROM MiTabla ExecuteReader()Para cuando quieres leer el resultado de uno o varios SELECTs usando un DataReader.
// la prctica recomendada es alamacenar este string de conexin // en el archivo .config de mi aplicacin (web.config o app.config). // // en este ejemplo, me estoy conectando a la instancia local // SQLEXPRESS, a una base de datos llamada AdoNetDemo utilizando // las credenciales del usuario que ejecuta mi aplicacin string miStringDeConexion = @"Data Source=.\SQLEXPRESS;Initial Catalog=AdoNetDemo;" + "Integrated Security=True"; using (SqlConnection miConexion = new SqlConnection(miStringDeConexion)) { miConexion.Open(); // un INSERT utilizando SQL int registrosAfectados = 0;

string miQuery = "INSERT INTO Peliculas (Titulo, FechaDeAdquisicion, Precio) " + "VALUES ('El Santo y Blue Demon vs. las Vampiras','2006-08-06',15.65);"; SqlCommand cmd = new SqlCommand(miQuery, miConexion); cmd.CommandType = System.Data.CommandType.Text; registrosAfectados = cmd.ExecuteNonQuery(); // registrosAfectados ahora tiene valor de 1; // ahora un SELECT COUNT(*) usando SQL int numDeRegistros = 0; string otroQuery = "SELECT COUNT(*) FROM Peliculas;"; SqlCommand comandoParaContar = new SqlCommand(otroQuery, miConexion); numDeRegistros = Convert.ToInt32(comandoParaContar.ExecuteScalar()); // finalmente, un ejemplo de como leer todos los registros de una tabla SqlCommand miCommando = new SqlCommand("SELECT * FROM Peliculas;", miConexion); SqlDataReader speedy; speedy = miCommando.ExecuteReader(); } // using cerrar la conexin

Un momento! Ya sali el DataReader! Supongo entonces, que sera buena idea hablar de ellos.

DataReaders y DataSets
Cuando quieres leer datos, tienes de dos sopas en .NET: usar un DataReader o usar un DataSet con unDataAdaper. Para ambos necesitars una Connection y al menos un Command (para el SELECT), pero la diferencia est en qu puede hacer uno y qu puede hacer otro. DataReader es un objeto ligero y sper rpido que te permite leer UN registro a la vez, leyendo hacia enfrente solamente. Es lo que se conoce como un firehose reader, porque avienta los datos como si fuera una manguera a presin. En otras palabras DataReader es como Speedy Gonzles: chiquito, prieto y medio feo pero bien rpido el desgraciao.

Por otro lado, el DataSet es como Porky Pig: medio ghey y ms chonchoporque contiene algunos subobjetospero que puede hacer ms graciosadas. Con esos nos vamos a clavar en unos momentos ms (sin albur), pero primero vamos a ver el patrn clsico para utilizar un DataReader:

Que en cdigo se vera ms o menos como lo siguiente:


// declarar conexion y comando; // declarar DataReader; // "abrir" el DataReader con el mtodo ExecuteReader() del comando; // leer los datos, uno por uno: while (reader.Read()) { // hacer algo con los datos que leo } // cerrar el DataReader

El mtodo Read() se encarga de leer los datos y al mismo tiempo, mover el cursor al siguiente registro. El mtodo regresa true si logr leer el siguiente o false si ya no hay ms registros que leer. A pesar de ser sencillo y eficiente, el DataReader tiene algunas desventajas como son:

Es solo-lectura. Si quieres actualizar datos tendras que ejecutar un Command por separado. No te dice informacin sobre los datos que ests leyendo, por lo que no solo tienes que conocer el tipo de datos que ests leyendo, sino el orden de las columnas. Suponiendo que tuviramos la siguiente tabla con la informacin de tu coleccin de pelculas:

Tendras que leerlos as:


string miStringDeConexion = @"Data Source=.\SQLEXPRESS;Initial Catalog=AdoNetDemo;" + "Integrated Security=True"; using (SqlConnection miConexion = new SqlConnection(miStringDeConexion)) { // variables para poner los valores de cada columna int id = 0; string titulo = string.Empty; DateTime fechaDeAdquisicion; Decimal precio = 0; miConexion.Open(); SqlCommand miCommando = new SqlCommand("SELECT * FROM Peliculas;", miConexion); using (SqlDataReader speedy = miCommando.ExecuteReader()) { while (speedy.Read()) { id = speedy.GetInt32(0); // la primer columna es el ID titulo = speedy.GetString(1); // la segunda columna es el Titulo fechaDeAdquisicion = speedy.GetDateTime(2); // etc... precio = speedy.GetDecimal(3); // hacer algo con los valores leidos. // // las variables ahora tienen el valor del registro actual // en esta iteracin. } } // using cerrar el DataReader } // using cerrar la conexin

As que si lo nico que necesitas es leer datos de manera eficiente, Speedy digo el DataReader es el que te conviene. Pero habr ocasiones en las que tengas que manipular varios datos a la vez, o necesites ver la relacin de datos entre varias tablas. Es ah cuando los DataSets y los DataTables son bastante tiles.

Un DataSet puede contener una o varias DataTable que representen datos de tu base de datos. Cada DataTable, tiene una coleccin de DataRows que representan los registros que fueron ledos. El papel del DataAdapter es el de sincronizador de datos por medio de sus dos mtodos principales, Fill() yUpdate(). La forma de trabajar sera: 1. Llenas tu DataSet 2. Haces tu desmadreactualizas, insertas, borras registros 3. Actualizas tu base de datos Una ventaja al usar un DataAdapter es que no tengo que preocuparme por andar abriendo y cerrando la conexin. Estos mtodos lo hacen automticamente. Con Fill() puedes llenar todo tu DataSeto una DataTable especfica de tu DataSetcon los datos de la base de datos. Para usarlo, debes primero configurarle al DataAdapter su SelectCommand, que es el que indica qu query debe ejecutar para traerse los datos. Si no planeas actualizar datos, pues este es el nico comando que necesitas configurarle.
// // // // // asumiendo que al principio se declar using System.Data.SqlClient; para usar ms fcilmente clases del SQL Server Data Provider y using System.Data; para usar DataSet, DataTable, DataRow, et. al.

string miStringDeConexion = @"Data Source=.\SQLEXPRESS;Initial Catalog=AdoNetDemo;" + "Integrated Security=True"; SqlConnection miConexion = new SqlConnection(miStringDeConexion); SqlCommand miCommando = new SqlCommand("SELECT * FROM Peliculas;", miConexion); SqlDataAdapter miAdaptador = new SqlDataAdapter(miCommando); // tambien habriamos podido utilizar la propiedad SelectCommand // miAdaptador.SelectCommand = miComando; DataSet porky = new DataSet(); // llenar mi DataSet de acuerdo al SelectCommand

miAdaptador.Fill(porky); // el DataAdapter automticamente cre un DataTable en mi DataSet // con la misma estructura que el resultado de mi query, // incluyendo nombres de columnas y tipos de datos // // ahora puedo leer los registros de la siguiente manera: foreach (DataRow registro in porky.Tables[0].Rows) { //registro["ID"]; //registro["Titulo"]; //registro["FechaDeAdquisicion"]; //registro["Precio"]; }

La manera ms sencilla de comprobar que mi DataSet o DataTable tiene ya datos es utilizando el visualizador que viene con Visual Studio:

Con Update() el DataAdapter intenta propagar los cambios que hayas hecho en tu DataSet hacia la base de datos. Cmo lo hace? Polvos de hada.

Bueno, en realidad usa una propiedad de cada DataRow llamada RowState, que puede tener valores como nuevo, sin cambios, modificado y eliminado. El estado de cada DataRow se ajusta en cuanto haces algn cambio a los datos. De esa forma lo nico que tiene que hacer el DataAdapter, cuando llamas Update() es recorrer todos los rows del DataSet e invocar el InsertCommand, UpdateCommand o DeleteCommand, de acuerdo a si el DataRow es nuevo, modificado o eliminado, respectivamente. Obviamente para que esto funcione, necesitas haberle configurado previamente esos comandos al DataAdapter. Aunque podras especificarlos manualmente, si quieres evitar la hueva errores al hacerlo, puedes utilizar unCommandBuilder, que automticamente los inferirel Insert, Update y DeleteCommanden base alSelectCommand.
string miStringDeConexion = @"Data Source=.\SQLEXPRESS;Initial Catalog=AdoNetDemo;" + "Integrated Security=True"; SqlConnection miConexion = new SqlConnection(miStringDeConexion); SqlCommand miCommandoSelect = new SqlCommand("SELECT * FROM Peliculas;", miConexion); SqlDataAdapter miAdaptador = new SqlDataAdapter(miCommandoSelect); SqlCommandBuilder miConstructor = new SqlCommandBuilder(miAdaptador); DataSet porky = new DataSet(); // llenar mi DataSet de acuerdo al SelectCommand miAdaptador.Fill(porky); // modificar algunos de los registros // al primer registro, ponerle el ttulo en maysculas porky.Tables[0].Rows[0]["Titulo"] = porky.Tables[0].Rows[0]["Titulo"].ToString().ToUpper(); // eliminar el 4to registro porky.Tables[0].Rows[3].Delete(); // actualizar la base de datos en base a los cambios // hasta antes este momento la BD sigue intacta miAdaptador.Update(porky); // los cambios fueron propagados a la BD.

Para ser un poco ms completos, hay que mencionar que DataSet tiene muchas ms moneras que no alcanzaremos a ver en este artculo. Por ejemplo, puede representar varias tablas de tu base de datos con todo y relaciones para mantener la integridad referencial.

Como en el siguiente ejemplo:

En otras palabras, puedes representar toda o una parte de tu base de datos por medio de un DataSet. Sin embargo, cuando manejas varias tablas al mismo tiempo, las cosas comienzan a ponerse interesantes cuando quieres llenarlas o actualizarlas. Quiz es por eso que en Visual Studio 2005incluyendo las versiones Expressahora trae soporte paraTableAdapters, que ser el tema del prximo artculo en esta serie.

Este es el primero de varios artculos que tratan sobre ADO.NET y las moneras que trae la versin 2.0 del .NET Framework. Si quieres averiguar ms sobre el tema, haz una bsqueda en este blog o dale clic a la etiqueta de ado.net. Si tienes sugerencias, correcciones u opiniones sobre este artculo o si tienes sugerencias para artculos nuevos de temas que te gustara ver en este blog, deja un comentario mediante los enlaces de abajo. Las imgenes y nombres de los personajes "Speedy Gonzales" y "Porky Pig" son propieadad de Warner Bros. y tomados sin permiso para fines de no-lucro. As que si piensan demandarme, ni se molesten, porque saldra corriendo y gritando como Flanders para quitar las imgenes y referencias de este blog.

Potrebbero piacerti anche