lunes 13 de diciembre de 2010

Linq to Classes - Llamadas a PAs que retornan consulta a tabla temporal

Hemos visto que LINQ To Classes da problemas al agregar PAs al DBML cuando el resultado de éstos es una consulta a una tabla temporal. Siempre deja como retorno un entero en lugar de un tipo complejo con los campos. Esto es debido a que una tabla temporal puede ser modificada durante la sesión y Linq entiende que no es seguro retornar una estructura que puede cambiar. La solución al problema consiste en declarar una variable TABLE en lugar de una tabla temporal.

CÓDIGO QUE NO FUNCIONA:

CREATE TABLE #T (CAMPO1 VARCHAR(12), CAMPO2 VARCHAR(15))

INSERT INTO #T SELECT CAMPO1, CAMPO2 FROM TABLA

SELECT * FROM #T

CÓDIGO QUE FUNCIONA:

DECLARE @T AS TABLE (CAMPO1 VARCHAR(12), CAMPO2 VARCHAR(15))

INSERT INTO @T SELECT CAMPO1, CAMPO2 FROM TABLA

SELECT * FROM @T

lunes 22 de noviembre de 2010

Serialización .NET

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim p = New Prueba() With {.Nombre = "Ismael", .Apellidos = "Zori"}
Dim s = New System.Xml.Serialization.XmlSerializer(GetType(Prueba))
Dim sw = New System.IO.StringWriter()
s.Serialize(sw, p)

MessageBox.Show(sw.ToString())
End Sub
End Class


_
Public Class Prueba
Private m_Nombre As String
Public Property Nombre() As String
Get
Return m_Nombre
End Get

Set(ByVal value As String)
m_Nombre = value
End Set
End Property

Private m_Apellidos As String
Public Property Apellidos() As String
Get
Return m_Apellidos
End Get
Set(ByVal value As String)
m_Apellidos = value
End Set
End Property
End Class

SQL Server - Encriptación

3 FORMAS DE ENCRIPTAR: Mediante claves simétricas, asimétricas y certificados

-- CLAVES SIMETRICAS
-- -----------------

-- CREACION DE CLAVE (SIMETRICA)
CREATE SYMMETRIC KEY CLAVE_DE_PRUEBA
WITH ALGORITHM = TRIPLE_DES
ENCRYPTION BY PASSWORD = 'MAMATEQUIEROMUCHO'


DECLARE @ORIGINAL AS VARCHAR(50)
DECLARE @CIFRADO AS VARBINARY(MAX)
SET @ORIGINAL = 'Menuda mierda de día'


-- ENCRIPTADO
OPEN SYMMETRIC KEY CLAVE_DE_PRUEBA DECRYPTION BY PASSWORD = 'MAMATEQUIEROMUCHO'
SET @CIFRADO = ENCRYPTBYKEY(KEY_GUID('CLAVE_DE_PRUEBA'), @ORIGINAL)
SELECT @ORIGINAL AS ORIGINAL, @CIFRADO AS CIFRADO
CLOSE SYMMETRIC KEY CLAVE_DE_PRUEBA


-- DESENCRIPTADO
OPEN SYMMETRIC KEY CLAVE_DE_PRUEBA DECRYPTION BY PASSWORD = 'MAMATEQUIEROMUCHO'
DECLARE @VALOR_RECUPERADO VARCHAR(50)
SET @VALOR_RECUPERADO = DECRYPTBYKEY(@CIFRADO)
SELECT @ORIGINAL, @VALOR_RECUPERADO
CLOSE SYMMETRIC KEY CLAVE_DE_PRUEBA



-- CREACION DE PROCEDIMIENTO ALMACENADO CIFRADO
ALTER PROCEDURE PA_INSERTAR_USUARIO
(
@NOMBRE VARCHAR(20),
@EMAIL VARCHAR(30),
@PASSWORD AS VARCHAR(20)
) WITH ENCRYPTION
AS
OPEN SYMMETRIC KEY CLAVE_DE_PRUEBA
DECRYPTION BY PASSWORD = 'MAMATEQUIEROMUCHO'
INSERT INTO USUARIOS
VALUES
(
@NOMBRE,
@EMAIL,
ENCRYPTBYKEY(KEY_GUID('CLAVE_DE_PRUEBA'), @PASSWORD)
)
CLOSE SYMMETRIC KEY CLAVE_DE_PRUEBA




-- CLAVES ASIMETRICAS
-- ------------------
CREATE ASYMMETRIC KEY CLAVE_DE_PRUEBA_A
WITH ALGORITHM = RSA_2048
ENCRYPTION BY PASSWORD = N'12345'


DECLARE @ORIGINAL AS VARCHAR(20)
DECLARE @CIFRADO AS VARBINARY(MAX)
DECLARE @RECUPERADO AS VARCHAR(20)


SET @ORIGINAL = 'A POR TODAS, HERMANOS'
-- NO SE NECESITA PASAR CLAVE PARA CIFRAR:
SET @CIFRADO = ENCRYPTBYASYMKEY(ASYMKEY_ID('CLAVE_DE_PRUEBA_A'), @ORIGINAL)
SET @RECUPERADO = DECRYPTBYASYMKEY(ASYMKEY_ID('CLAVE_DE_PRUEBA_A'), @CIFRADO, N'12345')


SELECT @ORIGINAL, @CIFRADO, @RECUPERADO



-- CERTIFICADOS
-- ------------
CREATE CERTIFICATE CERTIFICADO_DE_PRUEBA
ENCRYPTION BY PASSWORD = 'TORQUEMADA'
WITH SUBJECT = 'CERTIFICADO DE PRUEBA',
EXPIRY_DATE = '31/12/2010'


-- BACKUP:
BACKUP CERTIFICATE CERTIFICADO_DE_PRUEBA TO FILE='C:\BACKUP_CERTIFICADO_DE_PRUEBA.CER'


-- USO:
DECLARE @ORIGINAL AS VARCHAR(20)
DECLARE @CIFRADO AS VARBINARY(MAX)
DECLARE @RECUPERADO AS VARCHAR(20)


SET @ORIGINAL = 'A POR TODAS, HERMANOS'
-- NO SE NECESITA PASAR CLAVE PARA CIFRAR:
SET @CIFRADO = ENCRYPTBYCERT(CERT_ID('CERTIFICADO_DE_PRUEBA'), @ORIGINAL)
SET @RECUPERADO = DECRYPTBYCERT(CERT_ID('CERTIFICADO_DE_PRUEBA'), @CIFRADO, N'TORQUEMADA')


SELECT @ORIGINAL, @CIFRADO, @RECUPERADO

jueves 3 de junio de 2010

Cargar un DataTable desde un documento Excel

Se necesita tener Microsoft.Jet.OLEDB.4.0 y en propiedades del proyecto hay que especificar que la compilación se realiza para CPU x86 dado que no funciona la librería Microsoft.Jet.OLEDB.4.0 con x64.

string cs = "Provider=Microsoft.Jet.OLEDB.4.0;" +
            "Data Source=c:\\datos.xls;" +
            "Extended Properties=Excel 8.0;";
var objDataAdapter = new OleDbDataAdapter(
                  "SELECT * FROM [Hoja1$]", cs);
var tabla = new DataTable();
objDataAdapter.Fill(tabla);

Etiquetas de Technorati: ,,

miércoles 2 de junio de 2010

LINQ – Carga asíncrona

Ejemplito de carga asíncrona:

// El código se ejecuta al pulsar sobre un botón del formulario
private void toolStripButton1_Click(object sender, EventArgs e)
{
            lblCargando.Visible = true; 
            List<PADRE> resultado = null;
            var procesoCarga = new MethodInvoker(() =>
                         {
                            using (var ctx = new BDDataContext())
                            {
                               resultado = ctx.PADREs.ToList();
                            }
                         });
            procesoCarga.BeginInvoke(
                new AsyncCallback(
                    (r) =>
                    {
                      this.Invoke(new MethodInvoker(() =>
                      {
                         pADREBindingSource.DataSource = resultado;
                         lblCargando.Visible = false;
                      }));
                     }), null);
}

El código ctx.PADREs.ToList() se ejecuta por otro hilo, al finalizar esa instrucción dispara el callback que se encarga de asignar la fuente de datos recuperada por el hilo y de ocultar un label. Es importante tener en cuenta el que callback se ejecuta por el hilo por lo que cualquier acceso a controles del formulario hay que hacerlo utilizando Invoke o BeginInvoke con el objeto del formulario o del control que se desea actualizar.

sábado 15 de mayo de 2010

LINQ – Función IsNull en LINQ To SQL

Implementar la función IsNull en LINQ To SQL es sencillo. Consiste en crear el método en la clase parcial del DataContext de nuestro DBML.

En el ejemplo, vamos a crear una función IsNull para campos tipo DateTime.

Ir al código fuente de la clase DataContext de nuestro DBML (desde DBML > ver código fuente). Debería quedar más o menos como esto (nota: por motivos de ancho de la caja que contiene el texto de cada publicación dentro del blog pueden encontrarse líneas de código separadas que deberían ir en la misma línea):

Imports System.Data.Linq.Mapping
Imports System.Reflection

Partial Class BDDataContext

<FunctionAttribute(Name:="IsNull", IsComposable:=True)> _
Public Function IsNullDateTime( _
<Parameter(Name:="field", DbType:="DATETIME")> ByVal field As DateTime?, _
<Parameter(Name:="output", DbType:="DATETIME")> ByVal output As DateTime?) As DateTime?
      Return CType(Me.ExecuteMethodCall(Me, _
      CType(MethodInfo.GetCurrentMethod(), MethodInfo),field, _
            output).ReturnValue, DateTime?)
End Function

End Class

Como podemos observar mediante los atributos Parameter indicamos los dos parámetros de la función IsNull de SQL Server. En ellos se indica tipo de dato dentro de la base de datos.

Uso:

Using ctx = new BDDataContext()
  Dim resultado = From c in ctx.Categories _
    Order By ctx.IsNullDateTime(c.Fecha1, DateTime.Now)
_
   Select c
End Using

Esto mismo podemos aplicarlo para cualquier otra función que exista en SQL Server pero no en LINQ.

Etiquetas de Technorati: ,,

lunes 3 de mayo de 2010

LINQ – WITH(NOLOCK) de SQL Server

En muchas ocasiones necesitamos lanzar consultas rápidas, para recuperar datos sin importarnos demasiado si reflejan los últimos cambios “commitidos”, es decir, consulta teniendo en cuenta los últimos cambios aunque no se haya llamado a un commit.

Esta sencilla operación la realizamos fácilmente con SQL con una sentencia de este tipo:

“SELECT * FROM RECEPCIONES_CAB WITH(NOLOCK)”

Ahora bien, cuando realizamos una consulta utilizando LINQ To SQL nos encontramos que no existe ninguna palabra reservada o método que nos sirva para realizar este tipo de consultas. Para hacerlo tenemos que abrir una transacción de tipo ReadUncommited y ejecutar la consulta. Por ejemplo:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Transactions;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(
               object sender,
               EventArgs e)
        {
            using (var ctx = new
                     DataClasses1DataContext())
            {
                using (var scope = new TransactionScope
                                       (TransactionScopeOption.Required, 
                                        new TransactionOptions() {
          IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted 
                          }))
                {
                    ctx.DeferredLoadingEnabled = false;
                    var dlo = new System.Data.Linq.DataLoadOptions();
                    dlo.LoadWith<RECEPCIONES_CAB>(r => r.RECEPCIONES_LIN);
                    dlo.LoadWith<RECEPCIONES_LIN>(r => r.V_PALETS);
                    ctx.LoadOptions = dlo;

                    rECEPCIONES_CABBindingSource.DataSource = ctx.RECEPCIONES_CAB.ToList();
                }
            }
        }
    }
}

LINQ – Error “Se ha intentado quitar una relación entre TABLA_PADRE y TABLA_HIJA, pero una de las claves externas de la relación (TABLA_HIJA.FK) no se puede establecer a null”

¿CUANDO SE PRODUCE?
Al intentar eliminar un registro de una tabla hija que posee una relación con otra tabla. En el ejemplo: AVISO_RECEPCIONES_CAB -> AVISO_RECEPCIONES_LIN, al borrar un registro de AVISO_RECEPCIONES_LIN
Sólo ocurre con foreignkeys que no permiten nulos.

SOLUCIÓN:
Abrir el DBML para ver el XML (Abrir con… > Editor XML) y en la relación de la tabla HIJA añadir 'DeleteOnNull="true"'. Por ejemplo:

<Table Name="dbo.AVISO_RECEPCIONES_LIN" Member="AVISO_RECEPCIONES_LIN">
    <Type Name="AVISO_RECEPCIONES_LIN">
      <Column Name="AVISO_RECEPCION" Type="System.Int32" DbType="Int NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
      <Column Name="LINEA" Type="System.Int32" DbType="Int NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
      <Column Name="CODIGO_PRESOLICITUD" Type="System.String" DbType="VarChar(35)" CanBeNull="true" />
      <Column Name="REFERENCIA" Type="System.String" DbType="VarChar(20) NOT NULL" CanBeNull="false" />
      <Column Name="REFERENCIA_PROVEEDOR" Type="System.String" DbType="VarChar(20)" CanBeNull="true" />
      <Column Name="CODIGO_ALMACEN" Type="System.String" DbType="VarChar(5)" CanBeNull="true" />
      <Column Name="CANTIDAD" Type="System.Int32" DbType="Int NOT NULL" CanBeNull="false" />
      <Column Name="CANTIDAD_RECEPCIONADA" Type="System.Int32" DbType="Int NOT NULL" CanBeNull="false" />
      <Column Name="LOTE" Type="System.String" DbType="VarChar(20)" CanBeNull="true" />
      <Column Name="PRECIO_UNITARIO" Type="System.Decimal" DbType="Money" CanBeNull="true" />
      <Column Name="ORIGEN" Type="System.Byte" DbType="TinyInt" CanBeNull="true" />
      <Column Name="REVISION" Type="System.Byte" DbType="TinyInt" CanBeNull="true" />
      <Column Name="FECHA_PREVISTA_ENTREGA" Type="System.DateTime" DbType="DateTime" CanBeNull="true" />
      <Association Name="AVISO_RECEPCIONES_CAB_AVISO_RECEPCIONES_LIN" Member="AVISO_RECEPCIONES_CAB" ThisKey="AVISO_RECEPCION" OtherKey="AVISO_RECEPCION" Type="AVISO_RECEPCIONES_CAB" IsForeignKey="true" DeleteOnNull="true" />
    </Type>
  </Table>


En caso de tener que implementar un método parcial en el código fuente del DataContext para borrado (DeleteTABLA()) hay que crear una clase parcial de la tabla hija y crear una propiedad que duplique
la foreignkey (en el caso del ejemplo la FK es el campo AVISO_RECEPCION). Su valor se insertará en el método 'OnLoaded'. Esto se tiene que hacer así porque por motivo X deja el campo de la relación a Nothing y pierde ésta.
Ejemplo:
Partial Class AVISO_RECEPCIONES_LIN
   Private m_AVISO_RECEPCION_2 As Integer
   Public Property AVISO_RECEPCION_2() _
                       As Integer
      Get
          Return m_AVISO_RECEPCION_2
      End Get
      Set(ByVal value As Integer)
          m_AVISO_RECEPCION_2 = value
      End Set
   End Property
   Private Sub OnLoaded()
       m_AVISO_RECEPCION_2 = Me.AVISO_RECEPCION
   End Sub
End Class
Private Sub DeleteAVISO_RECEPCIONES_LIN( _
        ByVal instance As AVISO_RECEPCIONES_LIN)
   Me.ExecuteCommand("DELETE “ & _
          “AVISO_RECEPCIONES_LIN “ & _
          ”WHERE AVISO_RECEPCION = " & _
          instance.AVISO_RECEPCION_2 & _
          " AND LINEA = " & instance.LINEA)
End Sub

     Si es una VISTA, se puede duplicar el campo en la propia SELECT y lanzar el ExecuteCommand con el DELETE por ese campo duplicado.

LINQ – Campos calculados

1) Creamos una clase parcial en el DBML para la entidad sobre la que queremos añadir un campo calculado haciendo doble clic sobre el DBML. En el ejemplo en mi DMBL tengo una tabla llamada TIPOS_ENVIO:

Imports System.Data.Linq.Mapping

Partial Class BDDataContext
End Class
Partial Class TIPOS_ENVIO
    Public ReadOnly Property CAMPO_CALCULADO() _
                                      As String
        Get
            Return Me.TIPO_ENVIO.ToString() & _
                 " - " & Me.DESCRIPCION_TIPO
        End Get
    End Property
End Class

2) Para usarlo sólo tendremos que poner NOMBRE_CALCULADO en la propiedad del control en la que se indique el campo a enlazar. Por ejemplo, en una rejilla de Developer dentro de la propiedad FieldName de la columna. CUANDO CREAMOS EL ENLACE EL CAMPO CALCULADO NO APARECE EN LA PESTAÑA DE ORIGENES DE DATOS
   NO PASA NADA, SE PUEDE AGREGAR UNA NUEVA COLUMNA AL GRID CON EL FIELDNAME AUNQUE NO ESTÉ. El ejemplo, lo he puesto con una rejilla de Developer pero, puede ser utilizado con cualquier otro control, como una caja de texto o un label asignando un Databinding a la propiedad text con ese nombre de campo.

domingo 2 de mayo de 2010

Métodos de extensión en Visual Basic .NET

La forma de crear métodos de extensión difiere de VB.NET a C#. En esta ocasión vamos a ver como se hace con VB.Net.

1) Crear Módulo
2) Agregar referencia a System.Runtime.CompilerServices
3) Crear método agregando el atributo <Extension()>. En el ejemplo que ponemos a continuación vamos a crear un método de extensión para la clase string que se va a llamar AlternarMayusculas:

Module MisExtensiones
<Extension()> _
Function AlternarMayusculas( _
               ByVal cadena As String) As String
         Dim sw = False
         Dim sb as new System.Text.StringBuilder
         For Each c In cadena
                If sw Then
                     sb.Append(c.ToUpper())
                Else
                     sb.Append(c.ToLower())
                End If
                sw = Not sw
         Next
         Return sb.ToString()
End Function
End Module

4) Uso del método de extensión:

Dim cadena = “Arkansas, donde los hombres son muy hombres y las mujeres tambien”

MessageBox.Show(cadena.AlternarMayusculas())

Esto visualizarará un mensaje así: ArKaNsAs, DoNdE etc,etc

LINQ – Group Join: Hacer un LEFT JOIN

Ejemplo:

Dim resultado = From pais In m_Paises _
Group Join persona In m_Personas _
On pais.CodPais Equals persona.CodPais _
Into PersonasPais = Group _
From p In PersonasPais.DefaultIfEmpty() _
Select New With {pais.NombrePais, .Persona = p}

La variable resultado será una secuencia de objetos de un tipo anónimo compuesto por las siguientes propiedades: NombrePais (string) y Persona (objeto del tipo Persona, es decir, del tipo de dato contenido en la secuencia m_Personas). En caso de que el país no tenga ninguna persona el método DefaultIfEmpty() retornará nothing de modo que la propiedad Persona de la secuencia final tendrá nothing, de este modo ya tenemos el LEFT JOIN de Países a Personas, es decir, mostrar todos los países independientemente de si tienen personas o no.

LINQ – Group Join: Agrupación por unión de dos tablas

Ejemplo:

Dim resultado = From pais In m_Paises _
Group Join persona In m_Personas On _
pais.CodPais Equals persona.CodPais _
Into PersonasDelPais = Group, _
EdadMinima = Min(persona.Edad) _
Select pais.NombrePais, _
pais.CodPais, _
PersonasDelPais, EdadMinima


m_Paises tiene objetos de la clase Pais. Esta clase tiene las propiedades CodPais (string) y NombrePais (string).


m_Personas tiene objetos de la clase Persona. Esta clase tiene las propiedades NombrePersona (string), CodPais (string) y Edad (integer).


Esta es una de las consultas más interesantes que podemos realizar con LINQ, se trata de una mezcla entre JOIN y agrupación (lo haremos por medio de las palabras reservadas Group Join). 
Lo vemos con el ejemplo anterior: la variable resultado será una secuencia de objetos con las siguientes propiedades: NombrePais(string), CodPais(string), PersonasDelPais (secuencia de objetos del mismo tipo que los objetos contenidos en la secuencia m_Personas, es decir, objetos de la clase Persona) y EdadMinima (integer). ´


Como se ve hemos realizado una agrupación con otra tabla generando una secuencia (PersonasDelPais) y además hemos utilizado una función de agregado, en este caso Min para guardar la edad mínima dentro de ese grupo de personas pertenecientes a un país.

LINQ – InnerJoin

Ejemplo:

Dim resultado = From pais in m_Paises _
Join persona in m_Personas _
On pais.CodPais Equals persona.CodPais _
Order by pais.NombrePais, persona.Edad _
Select new with {pais.NombrePais, persona.NombrePersona, persona.Edad}

En el ejemplo realizamos el equivalente a un INNER JOIN de base de datos pero utilizando LINQ gracias a la palabra reservada Join. En este caso la variable resultado almacenará una secuencia de un tipo anónimo compuesto por tres propiedades: NombrePais, NombrePersona y Edad. La primera de las propiedades es recuperada de la secuencia m_Paises y las dos últimas de la secuencia m_Personas.

Los campos por los que se realiza el JOIN son indicados mediante la palabra reservada On y es importante utilizar Equals y no ‘=’.

LINQ – Group By: Agrupación dentro de una misma secuencia

Ejemplo:

Dim resultado = From persona In m_Personas _
Order By persona.CodPais _
Group By CodigoPais = persona.CodPais _
Into PersonasPorPais = Group

Partimos de una secuencia (por ejemplo un List(Of T)) y queremos generar una nueva secuencia de objetos con dos propiedades: CodigoPais que es una cadena con el código del país y PersonasPorPais que es una secuencia que contiene objetos con el mismo tipo de dato que los de la lista m_Personas.

En el caso del ejemplo también se aplica una ordenación por código de país.

 

sábado 1 de mayo de 2010

Presentación

_DSC1352

Mucho tiempo ha transcurrido, diez años ya!, desde que terminé mis estudios de informática. Son muchos los buenos recuerdos de aquella época, cuando internet empezaba a llegar a nuestras casas a través del modem y se avecinaba el efecto 2.000, también por aquel entonces surgieron cantidad de empresas debido al boom de las .com, yo mismo participé en todo aquello.

Mis comienzos como programador fueron curiosamente con un lenguaje emergente que estudié por mi cuenta, ASP. Trabajé en una empresa llamada Webmedia donde aprendí mucho HTML, JavaScript y ASP. Fue por poco tiempo, dado que decidí dejarlo para terminar mis estudios que en ese momento era lo más importante para mí, pero resultó ser muy intenso.

Finalicé mis estudios con muy buenos resultados y entré a formar parte en otra empresa llamada Eurosoft en la que desarrollabamos aplicaciones a tres capas utilizando MTS (lo que más tarde paso a ser COM+) programando la capa de negocio con Visual Basic y la de presentación con ASP, HTML y JavaScript.

Más tarde, buscando fortalecer mis conocimientos, me atrajo la idea de formar parte una empresa de Bilbao que se estaba estableciendo en Madrid. Posibilidades de trabajar en aplicaciones para el estado y grandes clientes. Mi labor allí sería de analista programador, eso también me motivaba bastante dado que para mí significaba dejar de ser un simple “picador” de código para formar parte en el diseño de la aplicación. Decidí formar parte de su equipo y aunque anduve el algún proyecto corto para el estado mi principal labor allí estuvo con la Universidad Menéndez Pelayo, donde coordiné a un equipo de cinco personas en un proyecto para el departamento de Administración de la universidad. El proyecto era, nuevamente, con ASP pero esta vez con COM+. También tenía partes con RDO (Remote Data Objects).

Una vez terminado aquel proyecto probé a hacerme autónomo pero no hubo mucho éxito, el trabajo no era suficiente así que volví otra vez a trabajar por cuenta ajena, tal vez en otro momento…

Al poco tiempo conocí a Vicente, de la empresa Comunytek. Necesitaban a gente para una aplicación para Ahorro Corporación, empresa muy conocida en gestión de fondos de inversión, muchos de los fondos ofrecidos por las cajas de ahorros son gestionados por esta entidad. Me atrajo la idea mucho, un sector que desconocía totalmente, el financiero, algo totalmente diferente a la típica informática de gestión. Allí estuve desarrollando una aplicación en Visual Basic 6.0 para gestión de fondos de inversión. Cuando terminamos allí Comunytek me envió a Ahorro y Titulización para un desarrollo junto a los informáticos de allí para gestión de fondos de titulización, nuevamente en Visual Basic 6.0 con COM+. Terminamos el desarrollo allí y comenzamos con el que hasta el momento me ha parecido el proyecto más apasionante de todos en los que he trabajado: el proyecto NEMO para el Banco Santander. Se trataba en un principio de un terminal de contratación y difusión para la mesa de derivados (futuros, opciones, rolos y otras estrategias) pero luego se fue ampliando, para deuda, se incluyó un sistema de gestión de quoting para deuda y warrants, etc. Una de las cosas interesantes de aquello era el tiempo real, desarrollamos aplicaciones de alto rendimiento utilizando tecnología Microsoft .NET con C#, comunicaciones con sockets, programación multihilo, etc. Aprendí muchísimo y tuve la enorme suerte de trabajar con Ian Marteens (autor de varios libros, entre ellos de la Cara Oculta de C#, libro que podéis adquirir desde su web http://www.marteens.com/) y de coordinar al equipo de .NET.

En Comunytek estuve desde el año 2.002 hasta abril de 2009, siete años muy interesantes pero también muy sacrificados, el trabajo estaba en Madrid y yo vivo en Guadalajara, el viaje diario acabó por agotarme y tuve que tomar una decisión que no fue nada fácil.

Entré en ICP Logística, un sector que desconocía pero creo que muy estratégico e interesante para mí. He sacrificado dinero y cargo por tener algo más de tiempo y, al menos de momento, lo agradezco, sobre todo ahora que recientemente acabo de ser padre.

En ICP estamos desarrollando aplicaciones con Visual Basic .NET con framework 3.5 bajo SQL Server 2008 utilizando Developer Express como componentes gráficos.

Terminada mi presentación explico el motivo de creación de este blog:

A lo largo de mi carrera profesional me he topado con esos típicos problemas al desarrollar que son reincidentes y que no te acuerdas de cómo se abordaban, con lo que te toca rebuscar entre código antiguo o bien navegar nuevamente por internet para conseguir información. Como estoy cansado de eso he decidido ir metiendo todas esas cosillas que me voy encontrando en este blog para que de paso le sirva a la gente que tenga el mismo problema.

No pretendo en absoluto hacer cátedra de nada de lo que diga aquí. Es probable que existan formas mejores de abordar los problemas pero yo pondré las que me han funcionado, por supuesto la gente es libre de hacer cualquier tipo de comentario siempre y cuando sea constructivo, que es de lo que se trata.

La mayor parte de las entradas que publicaré en este blog están relacionadas con la tecnología Microsoft .NET (C#, VB.Net) o con SQL Server que es lo que llevo manejando desde hace bastantes años.

Un fuerte abrazo