miércoles, 30 de junio de 2010

[ADO.NET] Hacer un Insert y no morir en el intento

Después de hacer una lectura de una base de datos, ¿qué mejor que hacer un Insert para demostrar nuestro poderoso dominio con la información? ADO.NET ofrece unas cuantas soluciones, de las cuales veremos una: empleando un SqlCommand.

Todos conocemos la instrucción Insert de SQL. Vale. Pues ya lo tenemos todo resuelto. Lo primero que tenemos que hacer es abrir la conexión y crear un string con el comando que queramos insertar. Después ejecutamos el comando, cerramos la conexión y asunto resuelto. Complicado, ¿verdad?

Aquí tenemos el código:

   1: string query = "INSERT INTO EQUIPO VALUES ('" + siglas + "','" + nombre + "')";
   2:  
   3: //usando un command builder, para evitar un sql injection como el siguiente:
   4: //insert into equipo values ('mer', 'merida fc'); delete from equipo where siglas='her';-- '');
   5:  
   6:        
   7: SqlCommand command = new SqlCommand(query, Conexion.Instancia);
   8:  
   9: if ( command.ExecuteNonQuery() == 1)
  10: {
  11:     ret = true;
  12: }

Como se aprecia, creamos un objeto SqlCommand con el string de la instrucción que queremos ejecutar (nótese que también podrían valer delete y update) junto con el SqlConnection. El SqlCommand tiene varios métodos de ejecución, entre ellos el ExecuteNonQuery que nos devuelve la cantidad de filas que se han modificado al ejecutar la instrucción. Sencilo e intuitivo, ¿verdad?

Pero lamentablemente, cada vez que alguien hace esto, Dios mata a un gatito. Esto es una muestra de una mala práctica, ya que no controla el fallo de SqlInjection. Este fallo consiste en algo normal y se produce por las siguiente causas:

  • Mal diseño: Tu capa de presentación no valida los datos.
  • Mal diseño: Tu capa de lógica no valida los datos.
  • Mal diseño: Tu aplicación provoca que se alteren datos que no debe.
  • Desastre: Borrar todo, seguridad?

En vista al código anterior, ¿que podríamos hacer en el código anterior? Un ejemplo bruto sería insertar en el campo del formulario el siguiente código:

   1: '); DELETE MASTER;

Lo cual la capa de datos, recibiría la siguiente cadena a ejecutar:

   1: INSERT INTO EQUIPO WHERE VALUES('');
   2: DELETE MASTER;
   3: ');

Sobran las palabras. ¿Qué soluciones dispone .NET para que esto no ocurra? El propio objeto SqlCommand. Anteriormente insertábamos como string toda la secuencia de comandos, con lo que la validación es muy compleja. Si en lugar de ello empleamos parámetros, estamos ganando en seguridad y estabilidad, además de la limpieza de código. La clase SqlCommand se encarga de validar los datos y evita que se pueda producir un SqlInjection. Veamos paso a paso cómo se hace:

   1: string query = "INSERT INTO EQUIPO VALUES (@siglas, @nombre)";
   2:  
   3: SqlCommand command = new SqlCommand(query, Conexion.Instancia);
   4: command.Parameters.Add(new SqlParameter("@siglas", siglas));
   5: command.Parameters.Add(new SqlParameter("@nombre", nombre));
   6:  
   7: if (command.ExecuteNonQuery() == 1)
   8: {
   9:     ret = true;
  10: }

A través del carácter @, indicamos que lo siguiente es un parámetro. Nótese que no importa siquiera el tipo de dato. Posteriormente, se crean los parámetros y se indexan internamente en el SqlCommand. Mediante SqlCommand.Parameters podemos acceder a ellos.

Como hemos visto, esto garantiza una cierta seguridad en el acceso a la BD de nuestra aplicación, además de aumentar la mantenibilidad del código y de la propia aplicación.

[eMeS] Videos del juego

Después de mucho sufrimiento, nos quedamos fuera de la Imagine Cup. De todas formas, tengo el placer de mostrar dos de los primeros videos que hemos publicado:

El primero de estos videos es el tráiler del juego. La protagonista del juego es Sara, que se embarcará en un mundo de fantasía llamado Iredia. Descubriremos cómo los sonidos toman forma y sentido, nos sumergiremos dentro del oído humano para comprenderlo, conoceremos criaturas misteriosas que nos ayudarán a atravesar este mágico mundo. ¿Suena apetecible, verdad? Aquí tenéis el video:

Por otra parte, uno de los trabajos que más importantes a la hora de elaborar en los videojuegos son las herramientas internas del equipo de desarrollo. Siempre que doy una charla de introducción a videojuegos con XNA, lanzo la siguiente pregunta “¿Qué aplicaciones conocéis que se puedan emplear para hacer un videojuego?”. La gente responde 2 ó 3, hasta que les muestro una diapositiva con un total de 50 aplicaciones comerciales distribuidas en diferentes secciones de videojuego: desde el motor de físicas, hasta sistemas de networking, programas de diseño 3d, retoque fotográfico, IDE’s…hasta programas de gestión de proyecto. En nuestro caso, hemos desarrollado dos herramientas internas. Una de ellas, llamada SpriteSheetPacker, se emplea para generar los sprites desde los diversos frames de todos los elementos que dibujan el equipo de arte. Con ello creamos varios catálogos, como por ejemplo el catálogo de Sara, Animales, ciudad, campo, etc.

Otra de las herramientas y más enfocada al diseño del juego es el editor de niveles, que como su nombre bien indica sirve para crear y editar todos los niveles. A través de esta herramienta podemos colocar todo tipo de elementos en los mapas, como por ejemplo nubes, personajes, fondos, árboles, suelos, colisiones… además de otros elementos que no se ven, como los waypoints (que sirven para que elementos recorran paths definidos por el mapa) los puntos de inicio y muerte además como los disparadores de eventos. Con estos disparadores se ejecutan programas de scripts que hemos creado, y estos scripts también se pueden crear y editar desde el propio editor. Un ejemplo de script es el resultado de eventos que se producen, como una roca que cae. Sin más dilación, aquí dejo el video:

P.D: Remarco que los videos son algo antiguos y hay infinidad de cosas que han mejorado y cambiado. Pero esas cosas, ya las veréis cuando el juego se lance al mercado!

lunes, 21 de junio de 2010

Probando código

   1: if (funciona )
   2: {
   3: System.Console.WriteLine(“Fiestah”);
   4: }
   1:  int x = 5;
   1:  //Esto es un comentario
   2:  int x = 5;
   3:  int y = 10;
   4:  if ( y -5  > 5 )
   5:  {
   6:   
   7:  }