Developer Community Days en Cd. Juárez

jueves 31 de agosto de 2006 | categorías: , | 0 comentarios -- da clic aquí para dejar el tuyo

Paso #1: Anota en tu calendario (palm pilot, celular, tamagochi o lo que sea):

Developer Community Days, martes 17 de octubre en el Tec De Monterrey, de 4 a 9 PM

¿Ya lo anotaste? ¿No? OK, te espero...

¿Ya?

Muy bien,

Paso #2: Ve a esta dirección ahorita mismo y vota por los temas que te gustaría se trataran ese día. Los temas potenciales incluyen todas las cosas nuevas y chidotas: Desarrollo con .NET Framework 3.o (WPF, WCF, WF), Atlas, desarrollo para Office 2007, etcétera.

¡Ah! y si quieres, participa en el concurso para ganar un Xbox 360 o uno de los 25 libros sobre temas de desarrollo que estarán dando como premio.

¿Ya votaste?

¿No? Mmmta.

Ok, te espero otro rato.

¿Ya?

Excelente.

Paso #3: ¡Asiste! Sí, ya sé que tienes mucho trabajo, pero es bueno ir a estos eventos para desempolvarse, conocer tecnologías nuevas y conocer otros desarrolladores de la localidad. O llévate a tus compas del trabajo y de la escuela, si no te quieres sentir como rechazado social. Si no eres de la raza que acude normalmente a las reuniones de la Comunidad .NET de Cd. Juárez, pues este es un buen día para comenzar. Va a estar buenísimo.

Demasiado beta-blogging

| categorías: , | 0 comentarios -- da clic aquí para dejar el tuyo

Ok, pues con la movida a Blogger Beta, Windows Live Writer Beta ya no quiso jugar. Demasiados betas supongo. Live Writer ya no quiere actualizar los estilos del blog localmente y tanto él como Blogger para Word hacen como que postean, pero no veo los posts en Blogger. Como que están poniendo todo en www.blogger.com en lugar de beta.blogger.com. En fin, solo para que lo consideren si andan queriendo experimentar con Blogger Beta.

Usando using

lunes 28 de agosto de 2006 | categorías: , , , , | 4 comentarios -- da clic aquí para dejar el tuyo

El día de hoy aprendí un tip bastante bueno de como usar using gracias a Eber Irigoyen.

Todo comenzó porque él hizo un comentario en el último artículo recalcando la importancia de usar using para TODOS los objetos relacionados con la base de datos (conexiones, comandos, transacciones, etcétera). A mí se me hacía un poco de overkill, pero ahora comprendo que en realidad sí es un buen consejo.

Por si no sabes ni de qué hablo, esta instrucción define un alcance (scope) explícito para un objeto, fuera del cual el objeto es automáticamente "dispuesto" (manda llamar su método Close() o Dispose()), incluso si se levanta una excepción dentro de ese bloque.

Aunque estrictamente hablando no es necesario, ya que hay un scope implícito cada vez que abres y cierras llavecitas en C#, para recursos limitados como conexiones de red, el scope explícito que crea el using ayuda a que el garbage collector reclame esos recursos más fácil y rápidamente.

Si no lo tuvieras, tendrías que hacer todo a punta de bloques try/catch/finally. Eso era algo que no me gustaba de VB 7--bueno VB .NET o "VB 2003", como le quieran llamar. Afortunadamente VB 8 (2005) ya lo trae.

En el artículo original no la quise complicar mucho con esto, pero así quedaría el "patrón de uso de un DataReader" usando try/catch/finally:

string miStringDeConexion =
    @"Data Source=.\SQLEXPRESS;Initial Catalog=AdoNetDemo;" +
    "Integrated Security=True";
string miQuery = "SELECT * FROM Peliculas;";
 
SqlDataReader speedy = null;
SqlConnection miConexion = null;
SqlCommand miCommando = null;
try
{
    // en cualquiera de las instrucciones de este bloque se podría
    // levantar una excepción
 
    miConexion = new SqlConnection(miStringDeConexion);
    miCommando = new SqlCommand(miQuery, miConexion);
    miConexion.Open();
    speedy = miCommando.ExecuteReader();
    while (speedy.Read())
    {
        // hacer mi desmater 
    }
}
catch (SqlException)
{
    // hacer algo para intentar recuperarme o re-lanzar exception
 // si no pienso hacer nada, es mejor omitir el catch
}
catch
{
    // hacer algo para intentar recuperarme o re-lanzar exception
 // si no pienso hacer nada, es mejor omitir el catch
}
finally
{
    // haya o no haya ocurrido excepción, siempre debemos asegurarnos
    // de cerrar las conexiones, DataReaders, etc.
    if (!speedy.IsClosed)
        speedy.Close();
    if (miConexion != null)
        miConexion.Close();
    if (miCommando != null)
        miCommando.Dispose();
}

Como puedes ver, es medio engorroso. Por eso el using es tan cool.

Pero, yo tenía mis reservas, porque cuando tienes varios objetos, es fácil--pensaba yo--que acabes con un chorro de usings anidados, lo cual no me gustaba:

// asumiendo que TipoA, TipoB y TipoC son clases que
// implementan IDisposable
using (TipoA a = new TipoA())
{
    using (TipoB b = new TipoB())
    {
        using (TipoC c = new TipoC())
        {
            // hacer mi desmater
        } // using dispone c
    } // using dispone b
} // using dispone a

Ahora, también sabía que using soporta declarar varios objetos del mismo tipo dentro del paréntesis. Algo así como esto:

// De nuevo, asumiendo que TipoA implementa IDisposable
using (TipoA a1 = new TipoA(), a2 = new TipoA(), a3 = new TipoA())
{
    // hacer mi desmater
} // using dispone a1, a2 y a3

Lo cual no es muy útil cuando tienes objetos de distintos tipos, como en el patrón de uso de un DataReader--donde tienes que usar SqlCommand, SqlConnection y SqlDataReader.

Así que por eso se me hizo tan chido cuando Eber me comentó que using soporta una sintaxis más o menos así:

// asumiendo que TipoA, TipoB y TipoC son clases que
// implementan IDisposable
using (TipoA a = new TipoA())
using (TipoB b = new TipoB())
using (TipoC c = new TipoC())
{
   // hacer mi desmater
} // using dispone a, b y c

De esa forma podría re-escribir el ejemplo de esta forma:

string miStringDeConexion =
    @"Data Source=.\SQLEXPRESS;Initial Catalog=AdoNetDemo;" +
    "Integrated Security=True";
string miQuery = "SELECT * FROM Peliculas;";
 
using(SqlConnection miConexion = new SqlConnection(miStringDeConexion))
using(SqlCommand miCommando = new SqlCommand(miQuery, miConexion))
{
    miConexion.Open();
    using (SqlDataReader speedy = miCommando.ExecuteReader())
    {
        while (speedy.Read())
        { // hacer mi desmater 
        }
    } // using manda llamar speedy.Close()
} // using manda llamar miConexion.Close() y miComando.Dispose()

Ahora, nomás de payaso modifiqué un poco el código para verificar que en realidad se estuvieran mandando llamar los Dispose(), agregando manejadores para el evento Disposed tanto de la conexión como del comando de la siguiente forma:

public static void UsandoUsing() {
 
    string miStringDeConexion =
        @"Data Source=.\SQLEXPRESS;Initial Catalog=AdoNetDemo;" +
        "Integrated Security=True";
    string miQuery = "SELECT * FROM Peliculas;";
 
    using(SqlConnection miConexion = new SqlConnection(miStringDeConexion))
    using(SqlCommand miCommando = new SqlCommand(miQuery, miConexion))
    {
        miConexion.Disposed += new EventHandler(miConexion_Disposed);
        miCommando.Disposed += new EventHandler(miCommando_Disposed);
 
        miConexion.Open();
        using (SqlDataReader speedy = miCommando.ExecuteReader())
        {
            while (speedy.Read())
            { // hacer mi desmater 
            }
        } // using manda llamar speedy.Close()
    } // using manda llamar miConexion.Close() y miComando.Dispose()
}
 
static void miConexion_Disposed(object sender, EventArgs e)
{
    Console.WriteLine("miConexion liberada");
}
 
static void miCommando_Disposed(object sender, EventArgs e)
{
    Console.WriteLine("miComando liberado");
}

¿El resultado?

Oh yeah.

ADO.NET para novatos

domingo 27 de agosto de 2006 | categorías: , , | 14 comentarios -- da clic aquí para dejar el tuyo

ADO.NET es la tecnología 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 común con esa tecnología. 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 mantenían un “cursor” o un apuntador al registro que querías leer. ADO te proveía métodos para navegar hacia enfrente o hacia atrás en el grupo de datos que te regresaba tu query para que pudieras leerlos y/o alterarlos. Todo esto se hacía en vivo y en directo sobre la base de datos. Las desventajas de esta tecnología eran algunas, pero la principal es que necesitas mantener una conexión abierta en todo momento para manipular los datos. Así que si tenías, digamos 20 licencias para conectarte a tu base de datos, pues fácilmente podías saturarlas con 20 usuarios que estuvieran utilizando la aplicación 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 estás metiendo el auto en tu cochera, cuando te lo topas y lo saludas:

—¿Qué tal vecino, qué cuentas?
—Pos fíjate 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 estás cayendo de sueño, 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 más mínima muestra de interés en la conversación vas a estar ahí otra hora y él todavía está hablando de lo gracioso que se ve su bebé recién nacido cuando regurgita y… ¡aaaAAARGHHH!

Ejem… ¿en qué estaba? ¡Ah sí!

Sin embargo, ADO.NET maneja un modelo “desconectado”, más que nada por que el otro no es el más óptimo en cierto tipo de aplicaciones como las de Web o dispositivos móviles. Es decir, la idea aquí es que te conectes a la base de datos (o cualquier otro almacén de datos), hagas lo que tengas que hacer y te desconectes, liberando lo más rápido posible recursos de red, licencias, etcétera. Puedes mantener si gustas una copia cacheada de los datos en memoria, y luego cuando estés conectado nuevamente simplemente sincronizas tus datos con los del servidor—más 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 verás un montón 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 DataAplicación. Está bueno pues, ya fueron suficientes DataPayasadas.

Pero antes de meternos en ese tema, hay otros dos objetos que son más primitivos y que permiten que te conectes e interactúes con una base de datos: Connection y Command.

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

Ilustración conceptual de Connection y Command.  Da clic para ver la imagen en tamaño normal.

La clase exacta que utilizarás para establecer tu conexión 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, etcétera. Y aunque hay una forma en el .NET Framework 2.0 de hacer tu código “independiente del proveedor de base de datos”, no hay que mezclar el caldo con la sopa todavía; lo veremos en otro artículo.

Por ahora, si quieres interactuar con una base de datos SQL Server, tendrás que utilizar SqlConnection y SqlCommand; si quieres platicar con Oracle tendrás que usar OracleConnection y OracleCommand; y si quieres hacerlo con Access, puedes usar OleDbConnection y OleDbCommand. Sin importar cuál selecciones, los pasos para utilizarlo siempre son los mismos:

  1. Abres la conexión
  2. Haces tu desmadre (o sea, ejecutas tus comandos)
  3. Cierras la conexión

Usando SQL Server sería algo como esto:

// asumiendo que al principio se declaró
// using System.Data.SqlClient; 
// para usar más fácilmente clases del SQL Server Data Provider
 
SqlConnection miConexion = new SqlConnection("MiStringDeConexion");
miConexion.Open();
 
// Hago mis cosas
 
miConexion.Close();

La conexión requerirá de un string de conexión, de acuerdo al proveedor de datos, para indicar a qué base de datos conectarse y con qué credenciales. Por ahora utilizaré "MiStringDeConexión" para mostrar donde va ese valor.

Una práctica muy recomendada para evitar que se nos olvide cerrar la conexión es utilizar la instrucción using de C# (VB 2005 también 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, automáticamente invoca los finalizadores, Close() en este caso,
    // en cuanto se termina el scope de la instrucción.
}

El comando en sí se especifica utilizando la propiedad CommandText. Además, puedes especificar el tipo del comando que estás ejecutando con la propiedad CommandType:

  • Text—Cualquier query, incuyendo comandos para manipular la base de datos (CREATE TABLE, DROP TABLE, etc.)
  • StoredProcedure—Para ejecutar un procedimiento almacenado.
  • TableDirect—Para 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 métodos principales:

  • ExecuteNonQuery()—Para cuando tu instrucción no regresa una respuesta, p. ej. un INSERT, UPDATE o DELETE
  • ExecuteScalar()—Para cuando tu instrucción regresa UN SOLO registro con UN SOLO campo con un valor numérico, 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 práctica recomendada es alamacenar este string de conexión
// en el archivo .config de mi aplicación (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 aplicación
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 conexión

¡Un momento! ¡Ya salió el DataReader!

Supongo entonces, que sería 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 un DataAdaper. Para ambos necesitarás 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 súper rápido 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 presión. En otras palabras DataReader es como Speedy Gonzáles: chiquito, prieto y medio feo pero bien rápido el desgracia’o.

DataReader vs. DataSet. Da clic para ver la imagen en tamaño normal.

Por otro lado, el DataSet es como Porky Pig: medio ghey y más choncho—porque contiene algunos sub-objetos—pero que puede hacer más graciosadas. Con esos nos vamos a clavar en unos momentos más (sin albur), pero primero vamos a ver el patrón clásico para utilizar un DataReader:

Ilustración conceptual del uso de un DataReader. Da clic para ver la imagen en tamaño normal.

Que en código se vería más o menos como lo siguiente:

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

El método Read() se encarga de leer los datos y al mismo tiempo, mover el “cursor” al siguiente registro. El método regresa true si logró leer el siguiente o false si ya no hay más registros que leer.

A pesar de ser sencillo y eficiente, el DataReader tiene algunas “desventajas” como son:

  • Es solo-lectura. Si quieres actualizar datos tendrías que ejecutar un Command por separado.
  • No te dice información sobre los datos que estás leyendo, por lo que no solo tienes que conocer el tipo de datos que estás leyendo, sino el orden de las columnas.

Suponiendo que tuviéramos la siguiente tabla con la información de tu colección de películas:

Da clic para ver la imagen en tamaño normal.

Tendrías 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 iteración.
        }
    } // using cerrará el DataReader
} // using cerrará la conexión

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 relación de datos entre varias tablas. Es ahí cuando los DataSets y los DataTables son bastante útiles.

Ilustración conceptual del uso de un DataAdapter con un DataSet. Da clic para ver la imagen en tamaño normal.

Un DataSet puede contener una o varias DataTable que representen datos de tu base de datos. Cada DataTable, tiene una colección de DataRows que representan los registros que fueron leídos.

El papel del DataAdapter es el de “sincronizador de datos” por medio de sus dos métodos principales, Fill() y Update(). La forma de trabajar sería:

  1. Llenas tu DataSet
  2. Haces tu desmadre—actualizas, 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 conexión. Estos métodos lo hacen automáticamente.

Con Fill() puedes llenar todo tu DataSet—o una DataTable específica de tu DataSet—con 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 más fácilmente 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 automáticamente 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 más sencilla de comprobar que mi DataSet o DataTable tiene ya datos es utilizando el visualizador que viene con Visual Studio:

Imagen de cómo invocar el DataSet Visualizer. Da clic para ver la imagen en tamaño normal.

Imagen del DatSet visualizer. Da clic para ver la imagen tamaño normal.

Con Update() el DataAdapter intenta propagar los cambios que hayas hecho en tu DataSet hacia la base de datos.

¿Cómo 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 algún 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 podrías especificarlos manualmente, si quieres evitar la hueva errores al hacerlo, puedes utilizar un CommandBuilder, que automáticamente los inferirá—el Insert, Update y DeleteCommand—en base al SelectCommand.

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 título en mayúsculas
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.

Los datos despúes de la actualización. Da clic para ver la imagen en tamaño normal.

Para ser un poco más completos, hay que mencionar que DataSet tiene muchas más monerías que no alcanzaremos a ver en este artículo. Por ejemplo, puede representar varias tablas de tu base de datos con todo y relaciones para mantener la integridad referencial.

Ilustración conceptual de un DataSet. Da clic para ver la imagen en tamaño normal.

Como en el siguiente ejemplo:

Un ejemplo de un DataSet visto en el designer de Visual Studio. Da clic para ver la imagen en tamaño normal.

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 2005—incluyendo las versiones Express—ahora trae soporte para TableAdapters, que será el tema del próximo artículo en esta serie.


Este es el primero de varios artículos que tratan sobre ADO.NET y las monerías que trae la versión 2.0 del .NET Framework. Si quieres averiguar más sobre el tema, haz una búsqueda en este blog o dale clic a la etiqueta de ado.net.

Si tienes sugerencias, correcciones u opiniones sobre este artículo o si tienes sugerencias para artículos nuevos de temas que te gustaría ver en este blog, deja un comentario mediante los enlaces de abajo.

Las imágenes 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 saldría corriendo y gritando como Flanders para quitar las imágenes y referencias de este blog.

Bug de blogger con las etiquetas

| categorías: , , | 0 comentarios -- da clic aquí para dejar el tuyo

Acabo de descubrir una pulga menor con el beta de Blogger. Cuando sus labels contienen caracteres "especiales", p. ej. un acento, y luego quieren ver todos los posts con esa etiqueta al darle clic, no regresa ninguno de los posts. Me lo topé porque tenía algunos de ellos con la etiqueta de "epifanía". Blogger, entonces, genera el siguiente URL para esos enlaces: http://kamikazegeek.blogspot.com/search?label=epifan%C3%ADa Noten que en el parámetro "label" tuvo que hacer un encode del acento para la "í" en el valor de la etiqueta. ¿Cómo se resuelve? Quítenle los acentos a sus etiquetas :'( Ni Pedro, dijo Juan. Ahora mi categoría se parece al nombre de una morra con la que una vez salí: epifania--¿la que vino de Lituania? Así que ojo con eso.

Ya pude usar Blogger beta

viernes 25 de agosto de 2006 | categorías: , | 1 comentarios -- da clic aquí para dejar el tuyo

Estaba viendo hoy en el blog de Enrique Place, que ya le permitió cambiar el suyo a la versión beta de Blogger que les comenté hace algunos días. Desde entonces no había revisado si ya tenía esa opción yo activada, y de chiripa sí la tuve. Así que como buen Kamikaze, di el brinco sin pensarla mucho. Todo salió perfecto, excepto que se re-publicó todo el feed. Sorry por eso. Y como se andan poniendo muy pipiris nice con los blogs últimamente, pues no me quise quedar atrás y aproveché también para hacer unos cambios de layout. Además de que el nuevo Blogger me permite tener ya tags (bueno, labels o categorías, como le quieran llamar) lo cual lo hace más fácil de usar (espero). Sí, ya sé que este template está más pinche feo que el anterior, pero lo escogí razones 2 bien prácticas: para empezar no tiene tanto espacio vacío a los lados (y también se ajusta si cambian el tamaño del browser), lo cual deja más espacio en la columna de contenido, que es bastante útil cuando quieres copy-pastear código en tu post--como en los que tengo pensado publicar en estos días. Y pa' seguirle, el nuevo layout editor cae de perlas en aquellos momentos como este, en el que comienzo a ser víctima del sueñito NyQuil y del dolor de cabeza por el mugroso resfriado que me pegó. No tuve que pelearme para nada con el template pa' agregarle todas las tarugadas que quería, aunque significó que ahora sí quedó en pocho.

Fans de Delphi protestan

jueves 24 de agosto de 2006 | categorías: , | 3 comentarios -- da clic aquí para dejar el tuyo

Del artículo How to get people talking about your product en el blog de Eric Sink:

An example of great word-of-mouth

Delphi is a programming language and development tool from Borland. It is very highly regarded by its users. People often speak of how it allows developers to be extremely productive and how it generates very efficient standalone Win32 executables.

Borland is currently in the process of spinning out its developer tools into a new company which is informally referred to as "DevCo".

Three weeks ago I published chapter 9 of my Source Control HOWTO, in which I rather whimsically exaggerated by saying that Eclipse and Visual Studio are the only two IDEs left in the world. I figured that this might ruffle the features of anyone who is using one of the many other IDEs that admittedly still exist, but I didn't expect any sort of backlash.

Nick Hodges, product manager for Delphi, responded by asking his readers to go to my blog and post a comment in protest. As a result, 15 raving Delphi fans posted their complaints about Delphi and Borland's products in general.

#ifdef FRIENDLY_TRASH_TALK

Fifteen people? That's like 20% of all the remaining Delphi users on earth, right Nick?

;-)

#endif

¡Saludos al Edgar!

(Como diría el Chefi)

Evento de Workflow Foundation en El Paso

miércoles 23 de agosto de 2006 | categorías: , , , , | 0 comentarios -- da clic aquí para dejar el tuyo

El Grupo de Usuarios de .NET en El Paso nos está invitando a un evento el próximo Martes 29 de Agosto, de 6pm - 8:30 pm en el Buisness Building de UTEP, room 111.

Al evento vendrá una persona de Micorosft, J Sawyer, que es un "evangelista" de .NET, para hablar sobre Windows Workflow Foundation. (más info aquí).

Si se perdieron la plática en la reunión de mayo, o si quieren conocer más sobre el tema entonces échense una vuelta. Esta plática va a durar más que la que tuvimos nosotros (como 2 horas y media).

Los que estén interesados en acudir tienen que enviarle un correo a Tiffany Cynor a más tardar este viernes 25 de agosto para confirmar su asistencia. Su correo es:

Tiffany Cynor tmcynor@hotmail.com

ADO.NET en los próximos días

| categorías: , , , | 1 comentarios -- da clic aquí para dejar el tuyo

La semana pasada me tocó meter mi cuchara (sin albur) en la plática de ADO.NET.

Luego el viernes en a las 5:00 PM el Pepe estaba histérico porque la persona que iba a dar el taller tuvo que cancelar de último momento. Así que me habló para que entrara de bateador emergente.

Llegué el sábado medio ojeroso porque sí me desvelé preparando el taller para que tuviera cosas interesantes. Y valió la pena (o al menos le gustó al Pelos).

Aunque no pudimos tratar muchas cosas que yo hubiera querido sobre ADO.NET 2.0--Provider Factories, serialización binaria de DataSets, mejoras a la clase DataTable, etc.--sí alcanzamos a ver algunas: las enormes mejoras en el databinding para Windows Forms con el BindingSource, los TableAdapters y muchas de las mejoras en Visual Studio, desde el Designer de los DataSets, el panel DataSources y hasta las herramientas para refactorizar y generar Stored Procedures automáticamente con el mismo IDE.

Y no faltaron los comentarios del Edgar, que cada vez que yo mostraba algo chido--según yo--él se encargaba de recordarnos "Uuuu pos Borland hace eso desde hace 3 años". Jejeje, demmet. En fin.

Nuevamente utilizamos una versión Express de Visual Studio, esta vez fue Visual C# 2005 Express Edition, para que la raza se diera cuenta de lo potente que están estas herramientas gratis.

Lo que me di cuenta con la plática y el taller es que mucha raza todavía anda buscando más detalles sobre el tema, así que ya comencé a escribir un artículo(te) en español al respecto, completo con varias ilustraciones, incluyendo las que dibujé el día de la plática.

Sí ya sé que probablemente haya algunos otros por ahí, pero ya ven que tengo mi modo de decir las cosas. El artículo resume todos los conceptos respecto a ADO.NET que considero importantes, desde lo básico. Espero tenerlo listo para este fin de semana.

También tengo planeado una serie de posts (o quizá otro artículo) para cubrir los nuevos features que trae la versión .NET 2.0 y que no pudimos tratar bien en la plática o el taller.

Pensé en hacer un screencast (o varios) al respecto, pero soy pobre y tengo que mantener a las teiboleras, digo... no tengo espacio en donde hostear esos archivos por el momento. Si alguien quiere volutariarlo pues lo agradecería. Aunque creo que digo tarugadas más divertidas cuando escribo...

Así que si no ven posts míos lo que queda de esta semana ya saben por qué. (Ando en el Premier)

Wikis: escritura colaborativa

lunes 21 de agosto de 2006 | categorías: , | 0 comentarios -- da clic aquí para dejar el tuyo

Sí, ya sé que este es mi tercer post del día de hoy que menciona los wikis, y no nomás es porque me gusta la palabra (wiki-wiki-wiki-wiki-wiki-wiki), pero es que mientras más masticaba la idea, más me fue cayendo el veinte de la importante diferencia de escribir, por ejemplo un blog o una página "normal" y escribir en un wiki.

Yo, como alguien que se dá dotes de escritor wannabe, no me gusta que editen lo que escribo. Mis escritos son míos. Me costaron imaginación, tiempo y esfuerzo, y en un wiki cualquiera puede venir y desmadr, ejem, mejorar lo que yo escribí, al menos en la teoría.

Es decir si yo hago una página con un artículo bien padriuris llamado "Cómo ligar teiboleras en 3 sencillos pasos", puede llegar otro wey X y arruinar mi artículo poniendo una foto suya--me pasó esta semana... no lo del artículo de teiboleras, sino que alguien se confundió y editó una página accidentalmente con algo nada que ver. O peor aún, tu hermoso artículo puede ser la víctima de wiki vandalismo, según el tema y los permisos que hayas especificado. Pasa hasta en Wikipedia.

En fin, esto es el precio de la escritura colaborativa. Es un cambio de mentalidad al que apenas me estoy acostumbrando, pero siento que tengo que hacerlo, porque prefiero que "mis" cosas lleguen a ser lo mejor posible, en vez de que sean a mi manera. Aunque esto implique tener que aplacar mi ego un poco.

Wetpaint 'ta chidota

domingo 20 de agosto de 2006 | categorías: , , | 1 comentarios -- da clic aquí para dejar el tuyo

Esta semana me la pasé bastante tiempo escribiendo en el wiki del grupo de estudio. Escogimos abrir uno en wetpaint.com por dos sencillas razones:

(1) es estúpidamente fácil de usar y

(2) el hosting es gratis. Y como dice mi tío Horacio: "Dadas hasta puñaladas, nomás no muy profundas". Nunca he sabido si lo dice con o sin albur.

El caso es que no tiene nada absolutamente nada de dificultad abrir un wiki y usarlo. Es casi vergonzoso. Es como usar Blogger o Google Pages.

Lo que haces es, sacas una cuenta en wetpaint.com, le dices como quieres que se llame tu wiki y mandas invitaciones a la gente que quieres que participe. Las personas pueden tener 3 "niveles": moderador, escritor y miembro--no, no ese tipo de miembro... sucios.

Típicamente lo que vas a querer es que solo un grupo de escritores pueda crear y editar páginas, y el resto del mundo pueda hacer solo comentarios en las páginas. Pero si eres en verdad aventurado, puedes permitir que cualquier persona contribuya, agregue y edite las páginas en el wiki.

Wetpaint usa bastante AJAX lo cual hace la experiencia de escribir completamente grata. Checa la diferencia entre leer una página y editarla al darle clic en EasyEdit:

Nota que el área fuera del texto que vas a editar se ve ahora como grisecito y aparece un toolbar flotante. El editor te muestra tu texto exactamente como va a quedar después de que le das guardar. Además puedes manipular elementos no tan sencillos como tablas en el editor. Definitivamente es el mejor "control" de edición de texto que he visto hecho con DHTML y AJAX.

Ah, ¿y mencioné que se pueden suscribir a los feeds de las páginas en el wiki o de los comentarios para saber cuándo cambian?

En fin hay muchas posibilidades con un sitio de este tipo. Incluso lo estoy considerando severamente para algunas de las cosas que hemos querido hacer para sustituir el grupo de discusión que tenemos en MSN para la Comunidad .NET.

Échenle un ojo si necesitan un espacio de páginas colaborativas.

Grupo de estudio para certificación en .NET

| categorías: , , , | 1 comentarios -- da clic aquí para dejar el tuyo

¡Estoy súper contento! Esta semana, como de la nada, se armó en la empresa de El Paso en donde trabajo, un grupo de estudio de más de 30 personas que quieren obtener una certificación c0n .NET 2.0.

Esto fue lo que pasó: 3 o 4 monos de alguna forma recibieron vouchers gratis para hacer el primer examen. Algunas de ellas ya le moqueaban a .NET, pero otras eran completamente nuevas. Así que buscaron a alguien que ya tuviera certificación para que les diera un norte... y es donde me embarraron en el desmater.

Al principio eran solo 6 o 7 las personas interesadas. Escogimos un libro que les pudiera servir para aprender el material y luego acordamos en juntarnos rutinariamente 1 hora los martes y jueves después del trabajo para aclarar dudas.

Pues se presentaron como 16 monos a la primer reunión, algunos con la idea de que iba a ser un curso de certificación. Se aclaró que definitivamente NO era ese el rollo, sino un grupo de estudio. En otras palabras todos--incluido yo--seríamos alumnos y todos seríamos mentores. Se oye medio payaso y comunista pero en realidad esa es la idea.

Se estableció la meta de presentar el primer examen para mediados de diciembre, ya que los vouchers expiraban el 31. El libro que escogimos es de arriba de 1000 páginas, así que para cubrir el material tenemos que chutarnos como 1 capítulo por semana, lo cual no es imposible, pero sí implica galopar a trote veloz.

En otras palabras, iba a haber gente--bueno, nomás yo hasta ahora--que los apoyara aclarando dudillas, pero cada quien tenía que chutarse el material, hacer los ejercicios y practicar pos sí solos de acuerdo a un calendario de actividades que entre todos desarrollamos. Las juntas nada más iban a ser para aclarar dudas y decidir en las acciones que seguirían.

Pusimos un wiki para poder compartir material de estudio, preguntas, ligas interesantes, el calendario de actividades, etcétera. Y ya que lo vieron algunas otras personas de la empresa, la cosa en verdad comenzó a crecer(sin albur). Comenzó a salir raza de hasta por debajo de los cubículos, o al menos así parecía. Como que el "tener una página" ya lo convirtió en algo formal, cool, o qué se yo.

Para la reunión del jueves, se presentaron más personas interesadas. Tantas, que el viernes ya pasábamos de los 30 y tuvimos que decidir no aceptar más participantes.

¡Qué loquera! jamás imaginé que tendríamos que decir "¡no más!" en un grupo de dotneteros.

Y no lo hicimos por ojetes, sino sino porque la raza nueva no tendría tiempo suficiente para alcanzar a hacer todas las actividades planeadas para el próximo martes en el calendario y comenzarían a atrasarse--y quizá al resto del grupo.

Ahora que hay la inquietud en la Comunidad .NET de Cd. Juárez de hacer algo similar con lo del desarrollador 5 estrellas, quizá también se pueda armar un grupo de estudio o algo así para que se anime más raza.

Estaría chido, ¿no?

OK, uno más

| categorías: , | 0 comentarios -- da clic aquí para dejar el tuyo

Ya que andamos con la anunciadera de blogs de la Comunidad .NET, acaba de surgir uno nuevo. Es el blog de Manuel Iglesias (aka Menyx).

Meny es el chavo que nos dió la plática y el taller el mes pasado sobre AJAX y Atlas. Yo lo conocí por primera vez hace como 6 o 7 años cuando él estaba bien lepe, en su primer semestre de prepa y yo era su dizque profe de sistemas.

Ahora el "lepe" me dió clases a mi, y no es por nada, pero aprendí cosas bien chidas. Todavía, cada vez que lo veo y me dice: "¿Qué onda, profe?" pienso: ¿Quizá sea hora de que se lo diga yo a él?

Dos blogs más de la Comunidad .NET

jueves 17 de agosto de 2006 | categorías: , , | 2 comentarios -- da clic aquí para dejar el tuyo

Recientemente descubrí dos blogs adicionales de raza de la Comunidad .NET de Cd. Juárez que me parecieron bastante chidotas.

El primero es de un veterano ya de la Comunidad, Edgar Montoya, que comenzó a echarle los kilos escribiendo sobre herramientas de Borland para .NET, lo cual se me hace perrísimo. A ver si lo convencemos de que nos dé una plática de esto en el futuro próximo.

El segundo, es de un chavo que apenas conocí en persona este martes, Abraham (aka "Abe"). Ténía muchas ganas de conocerlo, ya que desde hace un par de semanas descubrí su blog acerca de Ubuntu y desarrollo para dispositivos móviles. También participa en un video blog sobre PDAs y similares, así que no se lo pierdan.

Abe ya accedió a darnos una plática para la Comunidad que bien puede ser la de este mes que entra, so stay tuned...

Juguetes nuevos para bloguear

martes 15 de agosto de 2006 | categorías: , | 0 comentarios -- da clic aquí para dejar el tuyo

Hoy descubrí dos herramientas nuevas que hacen el iniciar y escribir en un blog infinitamente más sencillo. Así que si antes tenías el pretexto de que escribir en el tuyo está de guácala por Web, o creías que tener uno bonito era muy complicado, sigue leyendo...

Yo soy bastante huev... práctico cuando se trata de tener un blog. Me gusta que se vean bonitos, pero definitivamente no me gusta pelearme ni con estilos ni con templetes, es más ni con HTML para ser sincero--suficiente de eso tengo en mi trabajo diario como para hacerlo cuando nomás quiero escribir y postear. Es por eso que me cayeron bien.

La primer herramienta que me topé hoy es Windows Live Writer de Microsoft. Aunque aún está en Beta--osea que puede estar medio buguienta--hasta ahora me ha funcionado de perlas.

Hay muchos programas similares que he intentado usar en el pasado, desde el add-in para Word de Blogger, w.bloggar--que al parecer no ha pagado su recibo de web hosting--, hasta Performancing que es una extensión de Firefox. Writer me gustó más que todos ellos por dos sencillas razones:

(1) Funciona con el proxy corporativo. Cosa que no logré ni a mentadas de progenitora con ninguno de los otros programas. No que me la pase posteando en horas de trabajo, ¿verdad? ahem...

(2) Cuando estás escribiendo una entrada, se trae los estilos de tu blog para que veas más o menos cómo se verá mientras lo escribes, así como un Web Preview, lo cual es fan-tástico. Check it out:

Windows Live Writer funciona con varios proveedores de blogs, incluyendo Blogger--el que uso yo, duh--y hasta con Windows Live Spaces si tienen una inclinación mazoquista por esas cosas.

La otra novedad, es precisamente la versión nueva, también en Beta--de Blogger. Esta nueva versión tiene cambios interesantes, de los cuales el menor de ellos es que ahora puedes utilizar tu cuenta de Google para firmarte en tu blog (sí, la misma que usan para su Gmail o Google Pages).

Lo que más me gustó de la versión nueva definitivamente es el nuevo editor de layout. Anteriormente tenías que darte un tirotote con el template de tu blog... con su sintaxis que usa una serie de tags no-estándar y con muchas clases de CSS para que se viera bien. Hasta para algo tan simple como agregar un link a tu lista de links interesantes tenías que editar la cosa esa y re-publicar todo tu blog... y ni hablemos de si querías poner algo "avanzado" como un feed de otro blog en el tuyo. Digo no era imposible ni particularmente difícil--si sabes algo de HTML y CSS.

Ahora es tan sencillo como agregar un elemento nuevo al layout, seleccionar el tipo y configurarlo. ¿No te gustó el orden? Tan sencillo como drag-and-dropear, igualito que el Google Page Creator.

Entre los elementos interesantes que puedes agregar están un feed de otro blog, un bloque de HTML o JavaScript arbitrario--para todos esos snippets como una licencia Creative Commons o una caja de búsqueda de Google, o qué se yo--, y una lista de Labels.

Los Labels--o tags, que es lo mismo--son otro de los features chidotas de esta versión nueva de Blogger, y se usan para lo mismo que en cualquier otra aplicación "Web 2.0", oséase, para categorizar cosas, en esta caso los artículos que publiquen. Estas etiquetas las especificas en el momento que vayas a postear el artículo.

Si quieren ver el resultado, pueden ver un blog de prueba aquí.

Ahora, se supone que el nuevo blogger incluye también varios templetes nuevos, aunque yo vi los mismitos, pero organizados de una forma más amigable. Lo que sí se puede hacer ahora, finalmente, es cambiar los fonts y los colores que vienen con el template sin tener que pelearse con CSS en absoluto.

A mi en lo personal--como se habrán dado cuenta--me gusta el font Georgia, y nomás por eso comencé a echarme el tirote con el template en la versión anterior, cosa que me tomó casi un día para que quedara como a mi se me antojaba, y acabé semi-hackando unos templates de TypePad, pa' que se den una idea del degenere... en fin ustedes ya no tendrán que pasar por eso. Gracias a Diosito.

Desgraciadamente, en estos momentos el beta de blogger está limitado. Si ya tienen una cuenta en blogger, solo a pocas personas se les está invitando a migrar su blog existente "estándar" a uno con la nueva funcionalidad. Pero, si de plano no sea aguantan la curiosidad--como yo--pueden ir directamente a beta.blogger.com y crear un blog nuevo, utilizando su cuenta actual de Google. Parece que después tendrán la opción de integrar ambos.

Happy blogging!