sábado, 4 de febrero de 2012

Gadget - Gadget MSDN Español

Introducción
Hace ya un tiempo navegaba por mi cabeza la idea de realizar un gadget para Windows que permitiera a los usuarios de MSDN en Español acceder a la información de una forma más rápida y práctica. Dicho pensamiento nunca se puso en marcha hasta que tuve conocimiento sobre la existencia de este aplicativo para la versión de las ayudas en inglés, hecho que me llevó a replantearme el objetivo, decidiendo cumplirlo y a su vez aprender lo necesario para lograrlo.
A continuación daré una breve explicación sobre el funcionamiento de cada una de las partes del gadget. Al final se encuentra el link de descarga.

Presentación
Esta aplicación está formada por 5 módulos:
  1. Pantalla inicial
  2. Configuraciones
  3. Últimos hilos
  4. Últimas conversaciones
  5. Novedades
Explicaré una por una:
  • Pantalla inicial
    Además de darnos acceso al resto de módulos posee otras funciones:
    1. Accesos directos a: FAQs (Preguntas Frecuentes), MSDN Home (Página de inicio de MSDN), Soporte MSDN, Reporte de Bug (Reportar bug o sugerencia enviando un mail a mi casilla de correo).
    2. Buscador: devuelve una ventana de IE (Internet Explorer) con los resultados obtenidos de acuerdo a las palabras claves ingresadas.


  • Módulo de configuraciones
    Nos permite configurar los datos que deseamos visualizar desde el gadget:
    1. Foros: disponemos de un listado de los foros de MSDN Español, de los cuales podremos tildar nuestros favoritos para luego ver sus últimos hilos.
    2. Nombre de Usuario: para visualizar nuestras últimas conversaciones debemos ingresar nuestro user name en este campo.


  • Últimos hilos: desde este módulo podremos visualizar las últimas preguntas/temas/hilos de los foros seleccionados en el módulo de configuraciones. Además contamos con un acceso directo a los foros de MSDN Español.


  • Últimas conversaciones: una vez cargado nuestro nombre de usuario podremos acceder a la visualización de nuestras últimas conversaciones en los foros de MSDN. Dentro de este módulo disponemos de accesos directos a nuestro monitor de actividades y nuestro perfil.


  • Novedades: puertadeenlace.net es el blog oficial de Microsoft, para Argentina y Uruguay, en el que se publican las últimas novedades referidas a dicha empresa. A través de este módulo tendremos un acceso rápido a las mismas.



Descarga e instalación
Descargar Gadget MSDN Español
Para instalar este gadget solo deben descargarlo, ejecutarlo y al recibir el mensaje de advertencia autorizar la instalación del mismo.

viernes, 13 de enero de 2012

Transact SQL - Obtener ID de registro insertado (SQL Server)

Introducción
Generalmente necesitamos guardar un registro e inmediatamente insertar otros relacionados en otras tablas. Un ejemplo claro sería el de la facturación, para el cual necesitamos por lo menos dos tablas: una para guardar la información de la factura y las partes implicadas, y otra para el detalle de la misma. Tal vez muchos se han encontrado con el problema de obtener el ID del registro recien insertado, para solucionar esto tenemos a nuestra disposición una función llamada SCOPE_IDENTITY.
(Para SQLServer CE investigar sobre @@IDENTITY).


Definición
SCOPE_IDENTITY() es una función capaz de devolver el valor de la columna de identidad (llave, index, etc) recien insertada.


Implementación
Para llevar a cabo la implementación de esta función tomaremos como ejemplo un caso en el cuál un registro se guarda en dos tablas: una tabla de Clientes y otra de Monitoreo de Actividad.


Estructura de Tablas

Clientes
  • Cli_Id (int) (identidad) (NO NULL)
  • Cli_Nombre (nvarchar(60)) (NO NULL)
  • Cli_Direccion (nvarchar(50))(NULL)
  • Cli_Telefono (nvarchar(30))(NULL)
  • Cli_Email (nvarchar(30))(NULL)


Monitor
  • Mon_Id (int) (identidad) (NO NULL)
  • Mon_IdRegistro (int) (NO NULL)
  • Mon_NombreTabla (nvarchar(50))(NO NULL)


Code-behind
C#
            //Variable de Conexión
            SqlConnection con = new SqlConnection("Data Source=USER\\SQLEXPRESS;Initial Catalog=basePrueba;Integrated Security=True");
            con.Open();

            //Variable que contendrá el valor de la columna de identidad devuelto por la función SCOPE_IDENTITY()
            int idRegistro = 0;

            //Armo el Query para Clientes
            //A la hora de declarar el query agrego la función SCOPE_IDENTITY()
            SqlCommand cmd = new SqlCommand("INSERT INTO Clientes " +
                                            "(Cli_Nombre, Cli_Direccion, Cli_Telefono, Cli_Email) " +
                                            "VALUES" +
                                            "(@nombre, @direccion, @telefono, @email) " +
                                            "SELECT SCOPE_IDENTITY()", con);

            cmd.Parameters.Add("@nombre", SqlDbType.NVarChar).Value = txtNombre.Text;
            cmd.Parameters.Add("@direccion", SqlDbType.NVarChar).Value = txtDireccion.Text;
            cmd.Parameters.Add("@telefono", SqlDbType.NVarChar).Value = txtTelefono.Text;
            cmd.Parameters.Add("@email", SqlDbType.NVarChar).Value = txtEmail.Text;

            //Ejecuto la consulta y obtengo el valor devuelto por la misma
            idRegistro = Convert.ToInt32(cmd.ExecuteScalar());

            //Armo Query para el Monitor de Actividades
            //En la consulta paso un parámetro con el valor obtenido de la consulta anterior
            cmd.CommandText = "INSERT INTO Monitor " +
                              "(Mon_IdRegistro, Mon_NombreTabla) " +
                              "VALUES" +
                              "(@idRegistro, @nombreTabla)";

            cmd.Parameters.Add("@idRegistro", SqlDbType.Int).Value = idRegistro;
            cmd.Parameters.Add("@nombreTabla", SqlDbType.NVarChar).Value = "Clientes";
            cmd.ExecuteNoQuery();

            con.Close();


VB.NET
        'Variable de Conexión
        Dim con As New SqlClient.SqlConnection("Data Source=USER\\SQLEXPRESS;Initial Catalog=basePrueba;Integrated Security=True")
        con.Open()

        'Variable que contendrá el valor de la columna de identidad devuelto por la función SCOPE_IDENTITY()
        Dim idRegistro As Integer = 0

        'Armo el Query para Clientes
        'A la hora de declarar el query agrego la función SCOPE_IDENTITY()
        Dim cmd As New SqlClient.SqlCommand("INSERT INTO Clientes " _
                                        & "(Cli_Nombre, Cli_Direccion, Cli_Telefono, Cli_Email) " _
                                        & "VALUES" _
                                        & "(@nombre, @direccion, @telefono, @email) " _
                                        & "SELECT SCOPE_IDENTITY()", con)

        cmd.Parameters.Add("@nombre", SqlDbType.NVarChar).Value = txtNombre.Text
        cmd.Parameters.Add("@direccion", SqlDbType.NVarChar).Value = txtDireccion.Text
        cmd.Parameters.Add("@telefono", SqlDbType.NVarChar).Value = txtTelefono.Text
        cmd.Parameters.Add("@email", SqlDbType.NVarChar).Value = txtEmail.Text

        'Ejecuto la consulta y obtengo el valor devuelto por la misma
        idRegistro = Convert.ToInt32(cmd.ExecuteScalar())

        'Armo Query para el Monitor de Actividades
        'En la consulta paso un parámetro con el valor obtenido de la consulta anterior
        cmd.CommandText = "INSERT INTO Monitor " _
                          & "(Mon_IdRegistro, Mon_NombreTabla) " _
                          & "VALUES" _
                          & "(@idRegistro, @nombreTabla)"

        cmd.Parameters.Add("@idRegistro", SqlDbType.Int).Value = idRegistro
        cmd.Parameters.Add("@nombreTabla", SqlDbType.NVarChar).Value = "Clientes"
        cmd.ExecuteNoQuery();
        
        con.Close()


Seudocódigo
1. Declaro variable de conexión y le asigno un Connection String
2. Abro la Conexión
3. Declaro la variable 'idRegistro' que contendrá el valor de la columna de identidad del registro recién insertado
4. Declaro variable Command y le asigno un CommandText
--CommandText: Insertar en Clientes: en los campos (campos) los valores (valores) y seleccionar el valor del campo de identidad
5. Agrego los parámetros necesarios
6. Ejecuto la consulta y obtengo el valor solicitado
7. Asigno CommandText
--CommandtText: Insertar en Monitor: en los campos (campos) los valores (valores)
8. Agrego parámetros necesarios
--Parametro 'idRegistro': lo igualo al valor obtenido en la consulta anterior.
9. Ejecuto el query
10. Cierro la conexión

martes, 6 de diciembre de 2011

WinForms - ErrorProvider

Introducción:
ErrorProvider es una herramienta que nos permite indicar al usuario la existencia de algún error asociado a un control determinado.



Implementación


  1. Agregamos la herramienta a nuestro formulario.
  2. Modificamos las propiedades que creamos convenientes, unas de las más importantes son las siguientes.
    • ErrorProvider1.BlinkRate: la velocidad con la que parpadea el icono que indica el error.
    • ErrorProvider1.BlinkStyle: establece si el icono parpadea o no.
    • ErrorProvider1.Icon: permite seleccionar el icono que se quiere mostrar el establecer un error.
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'Configuro el ErrorProvider, ustedes pueden hacerlo en tiempo de diseño.
            ErrorProvider1.BlinkRate = 0
            ErrorProvider1.BlinkStyle = ErrorBlinkStyle.NeverBlink
            ErrorProvider1.Icon = New Icon(Application.StartupPath & "\errorProvider_16x16.ico")
        End Sub
    
  3. Hacemos la validación y establecemos un error a través del método SetError.
        Private Sub ButtonValidar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonValidar.Click
            If TextBox1.Text = Nothing Then
                'Establesco un nuevo error
                ErrorProvider1.SetError(TextBox1, "Debe completar el campo.")
            Else
                'Oculto el error
                ErrorProvider1.SetError(TextBox1, Nothing)
            End If
        End Sub
    
Eso es todo, un detalle muy agradable a la vista.

Código Fuente

VB.NET
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Configuro el ErrorProvider, ustedes pueden hacerlo en tiempo de diseño.
        ErrorProvider1.BlinkRate = 0
        ErrorProvider1.BlinkStyle = ErrorBlinkStyle.NeverBlink
        ErrorProvider1.Icon = New Icon(Application.StartupPath & "\errorProvider_16x16.ico")
    End Sub

Private Sub ButtonValidar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonValidar.Click
        If TextBox1.Text = Nothing Then
            'Establesco un nuevo error
            ErrorProvider1.SetError(TextBox1, "Debe completar el campo.")
        Else
            'Oculto el error
            ErrorProvider1.SetError(TextBox1, Nothing)
        End If
    End Sub


C#.NET
        public Form1()
        {
            InitializeComponent();
            //Configuro el ErrorProvider, ustedes pueden hacerlo en tiempo de diseño.
            errorProvider1.BlinkRate = 0;
            errorProvider1.BlinkStyle = ErrorBlinkStyle.NeverBlink;
            errorProvider1.Icon = new Icon(Application.StartupPath + "\\errorProvider_16x16.ico");
        }

        private void buttonValidar_Click(object sender, EventArgs e)
        {
            if(textBox1.Text == "")
                //Establesco un nuevo error
                errorProvider1.SetError(textBox1, "Debe completar el campo.");
            else
                //Oculto el error
                errorProvider1.SetError(textBox1, "");
        }