jueves, 27 de noviembre de 2008

Como crear Reportes Dinámicos con Crystal Reports y C# en WebForms usando DataSets y DataTables

Hace tiempo me tope con la necesidad de generar reportes en ASP.NET e imprimirlos. Investigando un poco, me tope con el detalle que no es tan fácil realizarlo como sería en un ambiente de escritorio. De hecho, se complicaba un poco más ya que debía de utilizar DataSets dinámicos, es decir, generados durante el uso de la aplicación, no desde un principio.

Decidí utilizar Crystal Reports, ya que se encuentra implementado dentro de Visual Studio 2005, incluyendo opciones como exportación a diferentes formatos como Excel y PDF.

Investigando un poco, me encontré con un código proporcionado por Fernando Berenguer Doménech en el cuál explicaba el método para realizarlo. Basándome en este gran apoyo, pude dar con la solución que a continuación expongo:

Principalmente agregó al proyecto un reporte Crystal Reports desde el Explorador de Soluciones. Yo le deje el nombre de CrystalReport.rpt

Más adelante le daremos formato al reporte. Por mientras lo dejaremos tal cuál como se agrego. Posteriormente insertamos a nuestro formulario un CrystalReportViewer, al cuál yo le puse de nombre crv1; este control será por el cuál mostraremos nuestro reporte o archivo .rpt


Es importante mencionar que ya contamos con el DataSet que queremos imprimir. Recordando que dentro de este contamos con diferentes DataTables identificados por un índice o nombre.

public static DataSet ds1 = new DataSet();

Durante el desarrollo de la aplicación lleno mi DataSet con una consulta SQL.

Ahora veremos el código que utilicé para enviar a imprimir un DataSet generado dinámico.

/*Yo lo puse dentro del evento Page_Load*/
protected void Page_Load(object sender, EventArgs e)
{
/*Construimos un DataSet y un DataTable para ser enviados como origen de datos a Crystal Reports. El DataTable lo indentificaremos con un nombre especifico*/

DataSet myDS = new DataSet();

DataTable myDT = new DataTable("dataset");


/*Mezclamos el DataTable que acabamos de crear con el DataTable que proviene de nuestro DataSet donde esta el resultado de una consulta SQL. Para esto utilizamos el método Merge*/


myDT.Merge(ds1.Tables[0]);

/*Agregamos el nuevo DataTable al DataSet que será el origen de datos de Crystal Reports
*/
myDS.Tables.Add(myDT);


/*Ahora creamos un archivo XML que contendrá nuestro DataSet. En teoría, este será escrito temporalmente en este archivo, que a su vez se convertirá en el origen de datos en el Reporte de Crystal Reports. Cabe mencionar que es muy importante que se tengan los permisos necesarios en la carpeta*/
myDS.WriteXml(@"C:\Inetpub\wwwroot\proyecto\xml\report.xml");

/*Ahora cargamos el archivo .rpt De igual manera hay que considerar los permisos necesarios*/

CrystalDecisions.CrystalReports.Engine.ReportDocument myrpt;

myrpt = new CrystalDecisions.CrystalReports.Engine.ReportDocument();

myrpt.Load(@"C:\Inetpub\wwwroot\proyecto\rpts\CrystalReport.rpt");


/*Establecemos como Origen de Datos el DataSet que llenamos */

myrpt.Database.Tables["preview"].SetDataSource(myDS);


/*Llenamos el CrystalReportViewer con la información*/
crv1.ReportSource = myrpt; crv1.DataBind();
}

Ahora… aun no funciona como debería ser. Es turno de trabajar con el reporte CrystalReport.rpt y prepararlo para que muestre la información como debería de ser. En este archivo tendremos que configurar en el Explorador de Campos el origen con un DataSet creado en un archivo xml.

Aquí es muy importante considerar que en el DataSet, el DataTable y los campos deben de llamarse igual que a los del resultado de la consulta SQL. A continuación creamos el archivo report.xml


Nótese el nombre del campo después de “NewDataSet”, ”preview” es como se llama nuestro DataTable.

Una vez tengamos creada esta “Base de Datos Temporal”, nos ubicaremos en el CrystalReport.rpt y utilizaremos el Explorador de Campos para dar de alta nuestro DataSet del XML.


Sobre la opción Campos de Base de Datos, daremos clic derecho y elegiremos Asistente de Base de Datos. En la ventana nueva, abriremos la carpeta Datos del Proyecto y Objetos .NET; será entonces donde podremos elegir en Ruta del Archivo el XML que creamos anteriormente.


Ya que tengamos cargado el DataSet, lo pasaremos por completo a la lista de Tablas Seleccionadas. De esta manera habremos determinado como Origen de Datos nuestro DataSet, con un DataTable llamado “preview” y con sus campos; los cuáles podremos pasar manualmente a nuestro CrystalReport .rpt



A estos campos podremos darle el formato que deseemos, la ubicación en el reporte, etc. Si todo salió bien, al momento en que probamos nuestra aplicación, el DataSet en el XML será llenado y el reporte lo podrá visualizar desglosando el listado de registros.

Cualquier duda ya saben donde encontrarme.

lunes, 20 de octubre de 2008

PHP y Postgres

Es relativamente fácil utilizar la base de datos Postgres en PHP. Si anteriormente habías conectado PHP con MySQL, es practicamente lo mismo.

1.- Modificamos el PHP.ini para agregar la extensión de pgsql. En ambiente Windows basta con teclear en menú ejecutar php.ini para abrirlo y modificarlo. En linux deberas de localizarlo en la carpeta de Apache.

2.- Dentro de este archivo, en el caso de windows bastara con descomentar la siguiente línea:

extension=php_pgsql.dll

3.- En ambiente Linux son varias líneas que se pueden descomentar y modificar; cada una de ellas tiene comentado su descripción, por ejemplo:

pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0

4- Todo esto con el fin de preparar la conexión. Es importante reiniciar el servidor Apache una vez guardados los campos.

5.- Para establecer una conexión PHP - Postgres, crearemos un archivo al que llamaremos conec.php e incluiremos las siguientes lineas:

/*Utilizamos una función para establecer la conexión*/
function Conectarse()
{
/*Mediante una condicion determinamos si se establecio o no la conexion.
Usamoa la pg_connect donde colocamos los parámetros:
dbname=Nombre de la Base de Datos
port=Puerto de Conexion a la Base de Datos
user=Nombre de Usuario para conectarse
password=Password para conectarse*/
if (!($conexion = pg_connect("dbname=gyc port=5432 user=usuario password=password")))
{
/*Si la conexion no es exitosa se mostrara el siguiente mensaje y salimos*/
echo "No pudo conectarse al servidor";
exit();
}
/*No importa si se establecio o no la conexion, esta sera devuelta por la funcion*/
return $conexion;
}

/*Ahora mandamos a llamar la funcion*/
Conectarse();

6.- Este archivo lo podemos guardar en alguna parte de nuestro proyecto y usar su ruta absoluta, pero en el caso de este ejemplo, lo colocaremos en la misma carpeta donde estara el archivo en donde usaremos la Base de Datos. Este archivo se llamara ejemplosql.php




7.- En ejemplosql.php incluiremos el siguiente código:

/*Incluimos el archivo de conexión*/
include("conec.php");

/*Guardamos en una variable el valor retornado de la función de conexión*/
$con=Conectarse();

/*Guardamos en una variable la sentencia SQL, en este caso del tipo SELECT*/
$sql_select_1 = "select nombre, edad from alumnos where id_alumno = '10'";

/*Realizamos la conexión y ejecutamos la consulta SQL mediante la función
pg_Exec con los parámetros de conexión a la Base de Datos ($con) y la sentencia SQL ($sql_select_1)*/
$query_select_1 = pg_Exec($con, $sql_select_1);

/*Si todo salio bien, obtendremos un objeto con los datos obtenidos de la consulta SQL,
mediante la funcion pg_fetch_object. Solo para los casos de SELECT*/
$query_result_1 = pg_fetch_object($query_equipos);

/*Una vez obtenido los datos, los podemos todavia extraer de forma mas particular,
mediante los nombres de los campos y guardandolos en variables*/
$nombre = $query_result_1->nombre;
$edad =$query_result_1->edad;

/*Imprimos las variables, comprobando el resultado.*/
echo "El nombre es: ".$nombre;
echo "Y su edad es: $edad años";

8.- Hasta este punto, hemos logrado realizar una conexión PHP - Postgres. Si obtuvimos algun error, podremos buscarlo por medio del numero de línea, así mismo si el error esta en la sentencia SQL.

9.- La clase de sentencia SELECT que utilizamos es para obtener datos específicos en una sola fila. Si deseamos recuperar información en un resultado SELECT de mas de una línea:

/*Incluimos el archivo de conexión*/
include("conec.php");

/*Guardamos en una variable el valor retornado de la función de conexión*/
$con=Conectarse();

/*Guardamos en una variable la sentencia SQL, en este caso del tipo SELECT*/
$sql_select_2 = "select nombre, edad, grado from alumnos where edad < '18'";

/*Realizamos la conexión y ejecutamos la consulta SQL mediante la función
pg_Exec con los parámetros de conexión a la Base de Datos ($con) y la sentencia SQL ($sql_select_2)*/
$query_select_2 = pg_Exec($con, $sql_select_2);

/*Obtenemos el número de filas del resultado con la función pg_num_rows*/
$no_filas = pg_num_rows($query_select_2);

/*Mediante un ciclo for, leemos cada una de las filas*/
for ($i=0;$i<$no_filas;$i++)
{

/*Guardamos en un vector cada una de las filas durante el ciclo con la función
pg_fetch_array con los parametros del objecto SQL y el numero de fila durante el ciclo*/
$array_local = pg_fetch_array($query_ausencias_local,$i);

/*Creado el vector, y durante el ciclo, podemos leer cada una de las filas mediante sus posiciones*/
echo "Su nombre es: $array_local[0], tiene $array_local[1] años y esta en el $array_local[2] grado";
}

10.- Para el caso de sentencias SQL como update, delete e insert, se utiliza como se muestra a continuacion:

$sql_update = "update alumnos set nombre = 'Mauricio', edad = '24', grado = '8'";
pg_Exec($con, $sql_update);

jueves, 18 de septiembre de 2008

Windows vs Linux en 3 Rounds

Round 1
Round 2

Round 3

Linux vs Windows - Round 3 | Linux Adictos from Esty on Vimeo.

Como será el siguiente...?

Fuente: http://www.vivalinux.com.ar/articulos/mortal-kombat-linux-vs-windows.html

jueves, 11 de septiembre de 2008

Las Chicas de mis sueños... chicas Geek

Anteriormente habia platicado de lo genial que sería tener una novia Geek, sin embargo nunca imagine que hubiera tantas, por lo que el sueño se puede hacer realidad (que cursi!!!). Me encuentro con una lista de chavas Geek, conocedoras de Linux, incluso muchas de ellas desarrolladoras, con amplios conocimientos en aspectos tecnológico... y sobre todo muy guapas.

Celeste Lyn Paul: Diseñadora de interacción, investigadora y contribuidora del desarrollo de open source. También lidera el KDE Usability Project, mentor de OpenUsability Season of Usability y está involucrada en el desarrollo de Kubuntu. (Ya tiene novio T_T)





Erinn Clark: Una desarrolladora de Debian que también fue co-fundadora y lidera actualmente el proyecto Debian Women. Un proyecto muy interesante, pero al que solo pueden entrar mujeres.





Valerie Henson: Val (así le dice todo el mundo) es una hacker (UNA HACKER!!!!) del Kernel de Linux especializada en el desarrollo de filesystems. Actualmente trabaja para Red Hat.



Pia Waugh: Esta australiana está completamente dedicada al software libre. Es actualmente la presidenta de la organización Software Freedom Day y vicepresidente de Linux Australia. Al parecer tiene un gusto por las artes marciales... si sabe pelear y desarrollar en Linux... mis respetos la verdad.





Eva Brucherseifer: Ingeniera eléctrica de Alemania que está detrás de los proyectos KDE-Women, KDE-Edu y KDE-Solaris.



Y ellas son solo una pequeñisima muestra de la cantidad de mujeres profesionales dedicadas al mundo Linux, con exito en sus carreras y desarrollo profesional. Me parece genial que las mujeres esten entrando y fuerte en esta área en la que se creia solo para hombres.

Despues de escribir esto, me quedo enamorado de mas de una de la lista de arriba... tal vez tener una novia Geek no sea despues de todo un sueño gaujiro.

Chicas Geek, no dejen de visitar ¿que clase de novio les gustaria tener?.

sábado, 6 de septiembre de 2008

REC

Despues de tanto tiempo de no escribir en este Blog, regreso para recomendarles una película un tanto antigua, pero que no deja de estar buena. Del género de Horror, REC es una producción española co-dirigida por Jaume Balagueró y Paco Plaza. Fue estrenada en Noviembre del 2007 en España, pero llego a México este mes de Septiembre.



Lo interesante de esta película, es que esta hecha bajo el formato de un falso documental, muy al estilo de Cloverfield. Todo los hechos son narrados desde cámara al hombro, dando una sensación presencial de los hechos, aparte de marearte y llevarte uno que otro susto.




Una reportera y su camarografo llevan a cabo una investigación con los bomberos de la ciudad, los cuales acompañan a uno de sus tantos llamados de emergencia, sin imaginarse el horror que se desataría.



Lo interesante de la película, es que a pesar de manejar un tema un tanto ya usado, la forma en que se desarrolla te lleva a estar imaginando lo que realmente esta pasando, el por que de los hechos, y lo peor de todo... como sobrevivir. Esa sensación de huir con la cámara le da un toque de horror y hasta de sorpresa que no permite que te muevas de tu asiento por saber que pasará, hasta que ella misma hace que saltes del susto. Una de las mejores producciones españolas a mi parecer, ganadora de varios premios, como mejor actriz, mejor director, y mejores efectos especiales. REC es sin duda una película altamente recomendable para aquellos que gusten del cine de horror. Actualmente se esta construyendo el argumento de la 2a Parte, y en Hollywood ya preparan su versión, donde los hechos suceden en Los Angeles. Aquí les dejo el trailer de la película para que lo chequen.


viernes, 18 de abril de 2008

Niño Matemático predice el fin del mundo el 13 de Abril del 2036

Aunque falta mucho para que la dichosa fecha nos alcance, es interesante saber el potencial matemático de Nico Marquardt, un chavito de 13 años que corrigió los cálculos de la NASA acerca de un asteroide que pasará muy cerca de la tierra en unos años.

Segun la NASA, aproximadamente en el 2036, asteroide Apophis (Dios Egipcio de la Destrucción) pasará cerca de la tierra, casi a unos 32500 km, un distancia menor a la que hay entre nuestro planeta y la luna. Eso ocasionaría que a su paso impactará contra una enorme cantidad de satélites artificiales orbitandonos. Esto podría ocasionar el desvió de su trayectoria.


Ilustración del dios Apophis...

Si bien nos va, lo alejarían de nosotros. Si mal nos va, lo mandarían directamente a la tierra. Pero supongamos que el asteroide Apophis pasará sin hacernos daño. Siete años después, cuando le de la vuelta al sol, regresaría muy cerca de nosotros. La NASA calculó 2 entre 100,000 la probalidad de que nos impactará.

Pues el chaval, Nico Marquardt, desde el observatorio Instituto de Astrofísica de Postdam, calculó que en realidad las posibilidades son de 2 entre 1000, cien veces menor que la NASA. Esto significaría que en el 2029 el Apophis pasará muy cerca de la tierra, y 7 años despues podría impactarnos de lleno, matando millones de personas, lanzando un Tsunami devastador y cubriendo la tierra de una gruesa capa de polvo que no dejaría pasar la luz del sol en años... el resto ya se lo imaginan.

La NASA acepto su error, y reconoció los resultados de Nico como correctos. Esperemos que para ese tiempo Nico Marquardt pueda, con sus calculos matemáticos, encontrar una manera de salvarnos... si no tendremos que revivir a Bruce Willis para que vaya al asteroide y lo haga explotar otra vez.

miércoles, 19 de marzo de 2008

Gadgets Religiosos...la tecnología al servicio de la fé

Me encuentro con que la tecnología no esta peleada con la religión, como tal vez algunos pensarán. Al contrario, la iglesia católica ha demostrado muchas veces que es posible usarla para llevar la fe a cualquier parte del mundo... como el internet, tv de alta definición, entre otros.

Pero los siguientes gadgets son muy originales, listos para ser usados tanto en el ámbito religioso como para alguien que se sienta atraído por esta singular moda.

Una Biblia USB



Con este singular gadget, podrás llevar este hermoso libre en formato digital a cualquier parte. Solo introducelo en un puerto USB y podrás leer cualquier pasaje.

iRosario



Es un rosario que tiene sus propios auriculares y al conectarse con tu iPod, copiara en el el rosario todas las oraciones y misterios... ahora no hay excusa de que no me lo se.

Cruz MP3



Un singular Reproductor MP3 en forma de Cruz de 1 Gb de capacidad, minipantalla LED y controles para su cómodo manejo.

iBelieve



Dock para tu ipod schuffle, con el cual controlaras la reproducción de tu música.

Iglesia Portátil



Que no es posible casar en cualquier parte ya no es pretexto con esta iglesia inflable, lista para ser montada en un salón de fiestas, casa, jardín, etc. Cuenta con su propio organo.

Virgen USB



Memoria USB de 1 Gb de capacidad, cuyo imagen se iluminará al conectarse al equipo y cuando escribas información en ella.

Este post es creado sin el áfan de molestar a nadie, sin importar la fe que profesen. Con información de http://multimedia.eluniversal.com.mx/fotogaleria.html

jueves, 13 de marzo de 2008

Simbolos Mayor que > y Menor que < en Ubuntu

Busque y busque en la Web alguna ayuda acerca de como sacar los simbolos de Mayor que ">" y Menor que "<" en Ubuntu, pero nadie no encontre. Solo algunas burlas acerca de por que mi teclado no las traía... a razón de que era teclado de Laptop adaptado a EUA, es decir, la distribución de las teclas estaba en Ingles. Como rádico en México me era importante obtener esos símbolos.

En windows los obtenía mediante código ASCII, por que igual no era posible de la forma normal en un teclado de escritorio. Pero en Ubuntu no encontraba nada... ni siquiera en combinación de teclas.

Pero un día, jugando con las teclas salío:

< = Alt + Shift + z
> = Alt + Shift + x


Esto en idioma español latinoamericano. Espero que alguien le sirva esto.

viernes, 7 de marzo de 2008

Historia de una tabla autoreferenciada

Corrian los tiempos en que diseñaba una Base de Datos para un sistemita. La idea era una tabla que almacenará un catálogo de servicios con una descripción, un precio, etc. Al principio, no representaba mucho reto... era relativamente fácil la creación y edición de esta para después realizar las altas, bajas, consultas y modificaciones.

Pero sucedió lo que a muchos desarrolladores les tiene que pasar algún día. Los requerimientos cambiarón... y una sola tabla no sería suficiente. Ahora era necesario catálogar esos mismos servicios, y tal vez lo primero que viene a la cabeza es crear una tabla mas con los catálogos y relacionarlos con la tabla de servicios.

Sin embargo, en el caso de este desarrollador que se había dormido en sus clases de Base de Datos en los temas de Joins, SelfJoins, RigthJoins, etc., era algo que le complicaba su trabajo..., tener que crear esa clase de consultas SQL me ponía en un aprieto.

Tenía que encontrar una manera de resolver el problema sin complicar el acceso a los datos, sobre todo pensando a futuro que las consultas SQL podrían tardarse mucho en ejecutarse debido a la enorme cantidad de datos que algún día manejaría.

Así que, al método de prueba y error, se modificó el diseño de la tabla agregando dos columnas mas:



La columna TIPO y TIPO_RELACION resolvía mi problema. La idea era que cuando se agregará un cátalogo, este tendría automáticamente en su campo TIPO las letras CT que lo identifican como catálogo y en el campo TIPO_RELACION la letra T (o cualquier otra, incluso sin letra) concatenandole el ID del registro, que mas adelante sería utilizado.



Agregado el catálogo, ahora era posible agregar un servicio que pertenecierá a ese catálogo, relacionado por el campo TIPO_RELACION. La imágen muestra el registro 13, donde se agregó un catálogo, con TIPO CT y TIPO_RELACION C13. Posteriormente, agregando mediante el sistema un servicio, este pertenece al catálogo anterior, colocando en su campo TIPO C13. De esta manera "apuntamos" el servicio a directamente con el catálogo que lo contendrá. Cabe mencionar que el campo TIPO_RELACION se quedo vació ya que este servicio no contendrá a nadie mas.



Fue así como conseguí, de pura casualidad una tabla autoreferenciada... o eso me lo dijo un cuate... e investigando me di cuenta que es algo muy útil, pero pocas veces utilizadas en las Bases de Datos. Analizando este método nos dimos cuenta que no solo se aplica en un solo nivel, si no que incluso se presta perfectamente para mas niveles de jerarquía, como por ejemplo, clasificar los catálogos, en otro catálogo, o incluso los servicios, podrían contener en su interior mas servicios y variantes... y a su vez estos. Un estilo de árbol jerarquíco cuya implementación es mas barata que utilizar un sin fín de tablas y relacionarlas todas entre ellas.

Al final, las tablas autoreferenciadas me han funcionando muy bien, sin ninguna clase de problemas hasta la fecha.

jueves, 6 de marzo de 2008

Conectando PostgreSQL con Java

En este mini tutorial intentaré explicar la manera en conectar nuestra aplicación hecha en JAVA con la Base de Datos de PostgreSQL.

Primero, es necesario descargarse el JDBC Driver para PostgreSQL. Este se encuentra en la página http://jdbc.postgresql.org/index.html Obviamente, será necesario contar con nuestra Base de Datos funcionando para realizar las consultas necesarias.

Posteriormente hay que determinar la manera de agregar este Driver a nuestro proyecto. NetBeans ofrece una manera mas que sencilla.

Conociendo la ubicación de nuestro Driver y con el proyecto abierto, en el Panel de Proyectos, ubicamos en el Árbol de Proyecto la opción Libraries, clic Derecho en ella y seleccionamos Add JAR / Folder..., de esta manera estaremos
agregando ej .JAR del Driver que descargamos. Esto nos crea en nuestro proyecto una carpeta llamada "dist" y en ella otra de nombre "lib" donde esta nuestro Driver.

Ahora, teniendo lo necesario, podemos probar nuestra conexión con PostgreSQL y realizar lo que nos concierne, Altas, Bajas y Modificaciones a nuestras tablas.

Para empezar, debemos de importar lo siguiente:

import java.sql.*;

Cabe mencionar que hay una gran diferencia entre Select y Update, Insert o Delete, ya que no se aplican de igual manera. A continuación muestro el proceso para realizar un Select (en idioma geek, vamos a selectear)

public class Main{
public static void main(String[] args){

/*Variable para almacenar la URL de conexión a nuestra Base de Datos, si esta estuviera en otra máquina, necesitariamos estar registrados en ella y contar con su IP*/
String url = "jdbc:postgresql://localhost/moo";

try{

//Acceso al Driver
Class.forName("org.postgresql.Driver");

//La conexión con los parámetros necesarios
Connection con = DriverManager.getConnection( url,"postgres","postgres");

//Abrimos la conexión y la iniciamos
Statement stmt = con.createStatement();

/*Un ResultSet es como en .NET un DataSet, un arreglo temporal donde se almacenará el resultado de la consulta SQL*/
ResultSet rs;

//Una variable String para almacenar la sentencia SQL
String query = "select id as ID from moo.usuarios";

//En el ResultSet guardamos el resultado de ejecutar la consulta
rs = stmt.executeQuery(query);

//En un ciclo while recorremos cada fila del resultado de nuestro Select
while ( rs.next()){

/*Aqui practicamente podemos hacer lo que deseemos con el resultado, en mi caso solo lo mande a imprimir*/
System.out.println(rs.getString("ID") + "\t" + rs.getString("ID"));
}

//Cerramos la conexión
stmt.execute("END");
stmt.close();
con.close();
}
catch( Exception e ){

//Por si ocurre un error
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}

Para realizar todo aquello diferente a un Select, utilzaremos lo siguiente:

/*Variable para almacenar la URL de conexión a nuestra Base de Datos, si esta estuviera en otra máquina, necesitariamos estar registrados en ella y contar con su IP*/
String url = "jdbc:postgresql://localhost/moo";

try{

//Acceso al Driver
Class.forName("org.postgresql.Driver");

//La conexión con los parámetros necesarios
Connection con = DriverManager.getConnection( url,"postgres","postgres");

//Abrimos la conexión y la iniciamos
Statement stmt = con.createStatement();

//Una variable String para almacenar la sentencia SQL
String query = "update moo.usuarios set nombre = 'Mauricio' where id = '1'";

//Ejecutamos la consulta SQL
stmt.executeQuery(query);

//Cerramos la conexión
stmt.execute("END");
stmt.close();
con.close();
}
catch( Exception e ){

//Por si ocurre un error
System.out.println(e.getMessage());
e.printStackTrace();
}

Es muy importante tener en cuenta que si este método lo utilizas en una función para hacerla llamar cuando lo necesites, y quieras enviarle tanto argumentos como retornar resultados, en la función de Select las líneas siguientes NO deben de estar presentes:

stmt.execute("END");
stmt.close();

Y en la parte de Update, Insert o Delete, solo la siguiente línea:

stmt.execute("END");

Espero que sea útil esta información.

viernes, 22 de febrero de 2008

Subir imágenes al Servidor y Guardarlas en tu Base de Datos

Llega el momento de cualquier desarrollador Web... en la que tiene la necesidad de dar la oportunidad al cliente de subir imagenes al Servidor, tal vez su foto, avatar, etc. Así mismo, aquel que trabaje con Bases de Datos tambien buscará la oportunidad de guardar archivos de imágen en una tabla, para no tener problemas al momento de respaldar y no cargar con todos los archivos.

En el siguiente Post se presenta la forma básica de hacer estas dos cosas, utilizando .NET y C# aunque facilmente puede ser aplicado en cualquier lenguaje o BD.

En primer lugar, necesitamos agregar a nuestro código las siguientes referencias:

using System.IO;
using System.Text;
using System.Drawing;

Posteriormente, necesitamos el control FileUpload, el clásico cuadro de texto y botón para seleccionar la ruta del archivo que se desea.

El procedimiento se divide en dos partes, subir la imagen al servidor y codificarla para su almacenamiento en la Base de Datos. Esta codificación se realizará en Base64, lista para almacenarse en un campo tipo texto.

Iniciemos con el evento de un botón para subir la imagen:

protected void bt_agregar_Click(object sender, EventArgs e)
{
//Variable que almacenará el nombre de la imagen
string imagen = "";

//Determinamos si se tiene un archivo que subir, una vez ya seleccionado.
if (this.FileUpload1.HasFile)
{

//Se separa la extensión del nombre del archivo para validarla
string[] nomExt = this.FileUpload1.FileName.Split('.');
string tipoFile = nomExt[nomExt.Length - 1];

//Revisamos si el archivo cuenta con una extension valida, pudiendo agregar o quitar.
if ((tipoFile == "jpg") || (tipoFile == "png"))
{

/*Si se cuenta con la extensión válida, procedemos a guardarla en el Servidor. FileUpload1.SaveAs solicita una cadena de texto con la ruta y el nombre del archivo. Server.MapPath("~/") determina la ruta de nuestra aplicación en el servidor. Si deseamos, le concatenamos otra carpeta, previamente creada*/

this.FileUpload1.SaveAs(Server.MapPath("~/") + "//moo//" + this.FileUpload1.FileName);

//Guardamos el nombre de la imagen
imagen = this.FileUpload1.FileName;

//Obtenemos su tamaño en bytes una vez que esta ya en el servidor
System.IO.FileInfo info_img = new System.IO.FileInfo(Server.MapPath("~/") + "//moo//" + this.FileUpload1.FileName);

//Lo convertimos a double y calculamos su peso en KB.
double b_img = Convert.ToDouble(info_img.Length);

//Limitamos el peso del archivo
if (b_img <= (512*1024))
{

/*Si el tamaño es válido, codificamos la imagen en Base64, un previo antes de guardarla en la base de datos. Esto se hace mediante la funcion CodificarFoto. Le enviaremos a la funcion la ruta completa de la imagen en el Servidor. Nos retornara una variable con la imagen ya codificada en Base64*/

string img_bin = CodificarFoto(Server.MapPath("~/") + "//moo//" + this.FileUpload1.FileName);

/*Guardamos la informacion en la Base de Datos. La variable img_bin contiene la imagen, pero codificada en texto, lista para almacenarse en un campo de tipos Texto o String de la Base de Datos. En esta parte puedes utilizar el método que desees para guardarla*/

//Si lo deseamos, borramos del servidor la imagen, una vez que ya esta en la BD
File.Delete(Server.MapPath("~/") + "//moo//" + this.FileUpload1.FileName);
}
}
}
}
}//Fin del evento del boton

Ahora veamos la función para Codificar la Foto

public string CodificarFoto(string sNombreArchivo)
{
//Variable para almacenar la imagen codificada
string sBase64 = "";

//Utilizamos un FileStream para acceder a la imagen en el Servidor
FileStream fs = new FileStream(sNombreArchivo, FileMode.OpenOrCreate, FileAccess.Read);

//Utilizamos un BinaryReader para pasar los datos de la imagen a un arreglo de bytes
BinaryReader br = new BinaryReader(fs);
byte[] bytes = new byte[(int)fs.Length];
br.Read(bytes, 0, bytes.Length);

//Guardamos el arreglo de bytes
sBase64 = Convert.ToBase64String(bytes);

//Retornamos la variable
return
sBase64;

//Se libera memoria
fs.Close();
fs = null;
br = null;
bytes = null;

}

Por ultimo les dejo el código para descodificar la imagen. Se entiende que ya se habrá leido la Base de Datos y recuperado la cadena (imagen codificada)

private void DecodificarFoto(string sBase64, string nombre_file)
{
/*Guardamos en una cadena la ruta de la imagen donde se descodificará. Es decir, despues de este proceso, estara guardada en el disco duro del servidor*/
string sImagenTemporal = Server.MapPath("~/") + "moo//" + nombre_file;

//Utilizamos un FileStream para crear un nuevo archivo temporal
FileStream fs = new FileStream(sImagenTemporal, FileMode.CreateNew, FileAccess.Write);

//Un BinaryWriter para escribir la imagen descodificada
BinaryWriter
bw = new BinaryWriter(fs);

//Un arreglo de Bytes para descodificar la imagen
byte
[] bytes;
bytes = Convert.FromBase64String(sBase64);

//Escribimos la imagen
bw.Write(bytes);

//Liberamos memoria
fs.Close();
bytes = null;
bw = null;
sBase64 = null;

}