viernes, 31 de julio de 2009

Mostrar un mensaje en pantalla en una aplicación web ASP.Net

Puesto que en las aplicaciones web de ASP.Net no pueden utilizarse las Clases "MessageBox" ni "MsgBox" para mostrar un mensaje en pantalla, en este tipo de aplicaciones habrá que crear un método con el código adecuado y llamarlo, por ejemplo, desde el "evento Load" de la página en la que debe mostrarse.

El método que construye el mensaje en tiempo de ejecución debe seguir los siguientes pasos:
1º. Crear el Script.
2º. Registrarlo en la página en la que debe mostrarse el mensaje para que quede asociado a la petición al Servidor.
3º. Asociarlo a algún evento que pueda desencadenarse en esa página. Por ejemplo, al evento "click" de un "botón".

Veamos el código:


   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Web;
   5:  using System.Web.UI;
   6:   
   7:  namespace BlogSalvatrosh
   8:  {
   9:      public class Script : System.Web.UI.UserControl
  10:      {
  11:          /// <summary>
  12:          /// Este método registra en la página que vaya a cargarse un mensaje escrito en código JavaScript que solicita al usuario la confirmación de la eliminación de un registro y se asocia al evento "onclick" del botón Eliminar. Cuando se pulse el botón eliminar el mensaje se mostrará en pantalla.
  13:          /// </summary>
  14:          public void AsociarScriptMensajeAdvertencia()
  15:          {
  16:              //Creamos un Script en lenguaje "javascript" que asociaremos luego a la petición al servidor
  17:              System.Text.StringBuilder script = new System.Text.StringBuilder();
  18:              //Iremos concatenando el código hasta completar la función "MensajeAdvertencia()" que se ejecutará en el servidor
  19:              //tras el registro de la página:
  20:              script.Append("<script type= 'text/javascript' language= 'javascript'>");   //Se abre la etiqueta del Script y se indica que es de tipo javascript
  21:              script.Append("function MensajeAdvertencia(mensaje){");   //Nombre de la función javascript que recibe como parámetro un mensaje de texto
  22:              script.Append("if(!window.confirm(mensaje)){");  //Si el usuario hace click en "cancelar"
  23:              script.Append("event.returnValue=false;");  //A la propiedad "returnValue" del Evento  "event" se le asigna el valor "false" 
  24:              script.Append("return false;"); //Y se retorna false
  25:              script.Append("}");
  26:              script.Append("else{"); //En caso contrario, es decir, si el usuario hace click en "Aceptar"
  27:              script.Append("return true;");  //Se retorna true
  28:              script.Append("}");
  29:              script.Append("}");
  30:              script.Append("</script>"); //Se cierrra la etiqueta del Script
  31:   
  32:              //Registramos el script en la página que vaya a cargarse:
  33:              this.Page.ClientScript.RegisterStartupScript(typeof(Page), this.ClientID + "script", script.ToString());
  34:   
  35:              //Asociamos el atributo "onclick" del botón "BotonEliminar" a la funcion "MensajeAdvertencia" que se encuentra en el script registrado en el punto anterior
  36:              this.BotonEliminar.Attributes.Add("onclick", "javascript:MensajeAdvertencia('Desea eliminar este registro de la Base de Datos?');");
  37:          }
  38:      }
  39:  }

sábado, 25 de julio de 2009

Insertar un registro en una base de datos SQL Server utilizando un Procedimiento Almacenado en Visual C#.

Para insertar un Registro en una Base de Datos SQL Server utilizando un Procedimiento Almacenado (que por supuesto debe haberse definido previamente en la Base de Datos), Visual C# necesita conocer:
1º. El objeto (registro) que desea insertarse en la Base de datos, con todos sus campos y valores, el cual puede haberse definido en una Clase (por ejemplo una Clase "Articulo"). Este Articulo (o la Clase que sea) se pasa como un tipo "object" (que aquí hemos llamado "obj").
2º. Que, efectivamente, se va a utilizar un Procedimiento Almacenado.
3º. El nombre del Procedimiento Almacenado.
4º. Los parámetros de dicho Procedimiento.

A su vez, para que Procedimiento Almacenado pueda ser ejecutado, Visual C# exige conocer de cada parámetro del Procedimiento:
1º. El nombre del parámetro.
2ª. El tipo de dato SQL.
3º. El valor del parámetro.

Para obtener toda esta información vamos a recurrir a "Reflexion", una de las características esenciales de Visual C#, recorriendo las "propiedades públicas" del objeto "obj" que se desea insertar en la Base de Datos.

Quizá lo más complejo sea obtener el tipo de dato SQL, ya que los tipos de datos utilizados por Visual C# no son equivalentes a los tipos de datos SQL Server y, por ello, será necesario realizar una conversión explícita y evitar un error en tiempo de ejecución.

Veamos como hacerlo paso a paso:


   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Data;
   6:  using System.Data.SqlClient;
   7:  using System.Configuration;
   8:  using System.Reflection;
   9:   
  10:  namespace AccionBaseDatos
  11:  { 
  12:      public class Insertar
  13:      {
  14:          //Variable que se va a utilizar para las instrucciones "lock" cuando la Aplicación entre en un proceso crítico
  15:          private static string semaforo = string.Empty;
  16:   
  17:   
  18:          /// Inserta un registro en la Base de datos utilizando el Procedimiento Almacenado cuyo nombre recibe como parámetro de entrada.
  19:          /// Para obtener los parámetros del Procedimiento Almacenado habrá que leer los datos de los campos y sus valores que vienen definidos en el parámetro "obj" que es de tipo "object"
  20:          public bool GuardarRegistroConProcedimiento(IDbConnection idbConnect, string nomProcedimiento, object obj)
  21:          {
  22:              //Creamos el comando SQL con el nombre del Procedimieneto Almacenado:
  23:              SqlCommand sqlCmd = new SqlCommand(nomProcedimiento);
  24:              //Se llama al método que obtiene los parámetros que necesita el Procedimiento almacenado
  25:              sqlCmd = ObtenerParametrosDelObjeto(sqlCmd, obj);
  26:              //Le indicamos que el comando SQL es de tipo Procedimniento Almacenado
  27:              sqlCmd.CommandType = CommandType.StoredProcedure;
  28:   
  29:              return RealizarTransaccion(sqlCmd, idbConnect); //Se llama al método que realiza la inserción y devuelve true o false si la ha realizado o no
  30:          }
  31:   
  32:   
  33:   
  34:          /// Obtiene los parámetros que necesita el Procedimieneto Almacenado para poder ejecutarse a partir de las "propiedades públicas" del Objeto "obj"  que se van a obtener utilizando el método "GetProperties()"
  35:          public SqlCommand ObtenerParametrosDelObjeto(SqlCommand sqlComando, object obj)
  36:          {
  37:              SqlDbType sqlDbTipo;
  38:              string nombreCampo = string.Empty;
  39:              string typ = string.Empty;
  40:              object valor = null;
  41:   
  42:              //Para obtener las "propiedades públicas" del Objeto "obj" las recorremos utilizando un bucle "foreach" y el método "GetProperties()":
  43:              foreach (PropertyInfo propiedad in obj.GetType().GetProperties()) //El método GetProperties() devuelve la propiedad
  44:              {
  45:                  nombreCampo = propiedad.Name; //Obtenemos el nombre del campo que hemos hecho coincidir con el nombre de la propiedad
  46:                  typ = propiedad.PropertyType.Name; //Obtenemos el nombre del tipo de dato (nombre del tipo de dato que utiliza el Framework).
  47:                  //Para obtener el tipo de dato SQL llamamos al método que realiza la conversión de tipos:
  48:                  sqlDbTipo = ComprobarTipoDeDatoSql(typ);
  49:                  //Obtenemos el valor del campo a partir del valor de la propiedad pública del objeto:
  50:                  valor = propiedad.GetValue(obj, null); //Como las propiedades del objeto "obj" no están indizadas el segundo parámetro es null
  51:                  //Creamos una variable de tipo Parámetro SQL con el nombre el campo y el tipo de dato SQL:
  52:                  SqlParameter sqlParametro = new SqlParameter("@" + nombreCampo, sqlDbTipo);
  53:                  //Le asignamos el valor del campo obtenido del objeto "obj" al valor del parámetro:
  54:                  sqlParametro.Value = valor;
  55:                  //Añadimos el parámetro al comando SQL
  56:                  sqlComando.Parameters.Add(sqlParametro);
  57:              }
  58:              return sqlComando; //Devuelve el comando SQL con los parámetros obtenidos
  59:          }
  60:   
  61:   
  62:          /// Obtiene el tipo de dato SQL guardado en el parámetro "tipo"
  63:          public SqlDbType ComprobarTipoDeDatoSql(string tipo)
  64:          {
  65:              SqlDbType tipoDatoSql;
  66:   
  67:              if (tipo == "Int32")
  68:                  tipoDatoSql = SqlDbType.Int;
  69:              else if (tipo == "DateTime")
  70:                  tipoDatoSql = SqlDbType.DateTime;
  71:              else if (tipo == "String")
  72:                  tipoDatoSql = SqlDbType.NVarChar;
  73:              else if (tipo == "Float")
  74:                  tipoDatoSql = SqlDbType.Float;
  75:              else if (tipo == "Boolean")
  76:                  tipoDatoSql = SqlDbType.Bit;
  77:              else if (tipo == "Double")
  78:                  tipoDatoSql = SqlDbType.Real;
  79:              else if (tipo == "Decimal")
  80:                  tipoDatoSql = SqlDbType.Decimal;
  81:              else
  82:                  tipoDatoSql = SqlDbType.Variant;
  83:   
  84:              return tipoDatoSql; //Devuelve el tipo de dato SQL obtenido
  85:          }
  86:   
  87:   
  88:   
  89:   
  90:          /// Ejecuta un comando SQL en la base de datos utilizando el método "ExecuteNonQuery()"
  91:          private bool RealizarTransaccion(SqlCommand sqlCmd, IDbConnection idbConnect)
  92:          {
  93:              try
  94:              {
  95:                  lock (semaforo) //Con la instrucción "lock" se indica que el programa va a entrar en un punto crítico para evitar que se ejecuten simultáneamente otros subprocesos
  96:                  {
  97:                      if (idbConnect.State == ConnectionState.Closed) //Se comprueba el estado de la conexión. Si está cerrada vuelve a abrirse:
  98:                          idbConnect.Open();
  99:   
 100:                      sqlCmd.Connection = (SqlConnection)idbConnect; //Se inicializa el objeto SqlConnection con la propia conexión "idbConnect" indicando que la conexión es de tipo SQL
 101:                      int filas = sqlCmd.ExecuteNonQuery(); //Se ejecuta la instrucción SQL, devolviendo el número de columnas afectadas
 102:                      if (filas > 0)
 103:                          return true;
 104:                      else
 105:                          return false;
 106:                  }
 107:              }
 108:              catch (Exception)
 109:              {
 110:                  return false;
 111:              }
 112:              finally
 113:              {//Se cierra la conexión
 114:                  if (idbConnect.State == ConnectionState.Open)
 115:                      idbConnect.Close();
 116:              }
 117:          }
 118:      }
 119:  }

jueves, 23 de julio de 2009

Crear un Diccionario de datos de tipo Clave/Valor en Visual C#

Vamos a crear una estructura de datos de tipo "Diccionario de pares Clave/Valor" (un tipo Dictionary) en el que tanto el tipo de dato de la Clave como del Valor serán de tipo String (aunque podrían ser de cualquier otro tipo).

Estas estructuras son útiles cuando se precisa almacenar y recuperar datos que deban estar relacionados en pares de valores. Por ejemplo, el nombre de una serie de personas con su DNI, ó
el nombre de una serie de artículos con su precio, etc.

Cada par de datos Clave/Valor se almacenan dentro del Diccionario como una estructura de datos denominada "KeyValuePair" (TKey, TValue).

Los diccionarios de datos se suelen utilizar cuando sólo se necesitan algunas de las propiedades (Claves) de algún objeto de una Clase previamente definida y sus Valores correspondientes, aunque no hay ningún inconveniente en utilizarlo para guardar todas las propiedades del objeto.

En este caso crearemos un "Dictionary" para guardar los valores de varias propiedades de un supuesto objeto de tipo "libro". Veamos el código:


   1:  public Dictionary<string, string> CargarDiccionario()
   2:          {
   3:              //Creamos una estructura de datos de tipo "Dictionary":
   4:              Dictionary<string, string> miDic = new Dictionary<string, string>();
   5:   
   6:              //Supongamos que necesitamos guardar tres propiedades (codigo, titulo y precio) que vamos añadiendo al Diccionario con sus correspondientes valores (por ejemplo, 2442, D. Quijote de la Mancha, 52). Cuando el valor es de tipo numérico lo convertimos previamente a tipo string
   7:              miDic.Add("codigo", Convert.ToString(2442));    
   8:              miDic.Add("titulo", "D. Quijote de la Mancha");  
   9:              miDic.Add("precio", Convert.ToString(52));
  10:   
  11:              RecorrerDiccionario(miDic);
  12:   
  13:              return miDic;
  14:          }


Para recuperar los datos almacenados en un Diccionario de pares de Clave/Valor habrá que recorrer cada uno de sus elementos "KeyValuePair" utilizando un bucle "for each". En este caso sencillamente realizamos la lectura y escribimos los datos en la secuencia de salida standard:

   1:  public void RecorrerDiccionario(Dictionary<string, string> elDic)
   2:          {
   3:              foreach (KeyValuePair<string, string> kvp in elDic)
   4:              {
   5:                  Console.Write(kvp.Key);
   6:                  Console.Write(kvp.Value);
   7:              }
   8:          }
Webs amigas:
Eduardo Soriano
Solcan
Taller de Joyería