viernes, 25 de marzo de 2011

Herramienta para generación de Scripts de inserción de datos de forma ágil en SQL Server

 

Una tarea que puede tomar, algunas veces mucho tiempo y que puede ser desgastante, es generar scripts de inserción de datos, en tablas. Y lo frustrante, es que, en muchos escenarios, la información ya se tiene en las propias tablas, pero para facilitar el cargado inicial de datos, en otras bases de datos o el transporte de la misma información, se requiere disponer del Script de inserción de datos.
 
En este escenario, aplica muy bien, la herramienta o procedimiento almacenado InsertGenerator que se puede obtener en este enlace:
http://www.codeproject.com/KB/database/InsertGeneratorPack.aspx
 
Lo que se hace es crear el procedimiento almacenado, en la base de datos, donde se encuentran las tablas con la información, que se desea tener en el Script de inserción y ejecutarlo pasándole, como parámetro, la tabla, para la que se desea generar el Script, así:
 
exec InsertGenerator ClasificacionesVehiculo
 
Con sólo eso, ya, en la ventana de resultados de ejecución de las consultas, de la herramienta de ejecución de consultas de SQL Server, aparece, el Script de Insert.

blog1

Nada más fácil. ¡Que vacano!.
 
Sin embargo, como lo que se quería era sacar la información o script de inserción de varias tablas, se investigó un poco más y, primero que todo, se creó un Script, para generar las instrucciones de insert sobre las tablas requeridas:
 
exec BDHERMESPROD20110310.dbo.InsertGenerator ClasificacionesVehiculo
exec BDHERMESPROD20110310.dbo.InsertGenerator FormasPago
exec BDHERMESPROD20110310.dbo.InsertGenerator GruposUsuario
exec BDHERMESPROD20110310.dbo.InsertGenerator Menus
exec BDHERMESPROD20110310.dbo.InsertGenerator Formularios
exec BDHERMESPROD20110310.dbo.InsertGenerator Plataformas
 

 
Fijarse como, se indica la base de datos donde se encuentra definido el procedimiento almacenado InsertGenerator y el propósito de ello es ejecutar el Script desde la consola del DOS, a través de la utilidad SQLCMD y poder generar, así, de una vez, el script de inserción, para cada tabla, de una forma aún más rápida:
 
sqlcmd -SMVMsb102 -UIUSR_HERMES -PIUSR_HERMES -i GeneScriptsTiposBasicos.sql -o insert.sql
 
Aquí, entonces,
 
S: El servidor es MVMsb102
U: EL usuario IUSR_HERMES
P: La clave, la misma
i: El Script a ejecutar, en este caso, GeneScriptsTiposBasicos.sql, que contiene las instrucciones de generación del insert sobre las tablas, mostradas arriba.
o: El archivo donde quedará el resultado de la ejecución del Script GeneScriptsTiposBasicos.sql
 
Al dar enter y ejecutar el comando, efectivamente, se genera el Script, con las instrucciones de inserción sobre las tablas. Así:


blog2 

Lo que resta  entonces es utilizar la instrucción USE, para indicar la base de datos donde se ejecutarán los Scripts de inserción y modificar los textos del tipo:
(x filas afectadas)
Por la palabra reservada GO, como se muestra a continuación y listo.

blog3

De esta forma,  se obtienen los Scripts de inserción de datos sobre varias tablas, de una forma ágil y rápida.


Resumen de pasos:
1.       Crear el procedimiento InsertGenerator en la BD donde se encuentran las tablas con la información.
2.       Crear el Script de generación de inserts sobre tablas
Ejemplo:
exec BDHERMESPROD20110310.dbo.InsertGenerator ClasificacionesVehiculo
exec BDHERMESPROD20110310.dbo.InsertGenerator FormasPago
3.       Ejecutar la instrucción:
sqlcmd -S -U -P -i –o
 
En la consola de DOS.
Especificando, apropiadamente:
El servidor, el usuario y clave de conexión a la BD, el Script a ejecutar y el nombre del archivo con el resultado
4.       Adecuar el Script, para su ejecución, en SQL Server. Es decir, indicar la base de datos con USE y colocar los GO.

Espero que esta herramienta sea de utilidad.

miércoles, 23 de marzo de 2011

Covarianza y contravarianza en C#

 

Esto son otros nuevos conceptos que vienen con el Framewrok 4.0 de C# y son duros de entender. Mi propósito en este articulo, como el de muchos autores, es dar a entender los conceptos que hay detrás de la covarianza y contravarianza, para que así estos conceptos se puedan aplicar de una manera más natural, en los desarrollos de Software que así lo requieran.
 
Empecemos por indicar que, desde el punto de la física,
 
Co y Contra: Implican dualidad, lo que significa que los términos van juntos.
Varianza: implica movimiento.
 
Se puede inferir, entonces, que en estos términos, Covarianza significa “Con el movimiento” y Contravarianza “Contra el movimiento o en sentido opuesto al movimiento”.
 
Ahora, en nuestro campo, la programación orientada a objetos, en el marco del concepto de herencia, identificamos dos tipos de objetos:
 
1.       Tipos base
2.       Tipos derivados
 
Así las cosas, podemos imaginarnos a un tipo base interactuando en un programa (es decir, tener un movimiento o acción o cambio)  y sustituir el tipo base por el tipo derivado, ya que el tipo derivado “es un” tipo base. Por tanto, cuando es equivalente tener a un tipo derivado en lugar del tipo base, estamos ante la covarianza. La acción o movimiento que afecte al tipo base, le afecta en igual medida al tipo derivado y, por ello, son covariantes.
 
En sentido opuesto, se define la contravarianza, en donde es el tipo derivado el que se puede sustituir por el tipo base.
 
En la siguiente imagen, se trata de ilustrar ambos conceptos:

 CoContraVarianza
 
Con el auge y manipulación de delegados, se pensó en incorporar, en el lenguaje, características que permitieran realizar manipulaciones de estos, esperadas, dada una relación de herencia entre tipos dados.
 
Ejemplo:
 
Gato hereda de Animal y, entonces, se puede tener el siguiente delegado genérico:
 
delegate T Func1<T>();
 
Siendo así las cosas, podemos tener una instancia de este delegado que retorne un gato:
 
 
public Cat MyFunc()
{
    return new Cat();
   }
 
    Func1<Cat> cat = MyFunc;
 
 
Debido a que un Gato es un Animal, tenderíamos a pensar, que debería ser viable asignar un Gato a un delegado que retorna un Animal, es decir, tener algo así:
 
Func1<Animal> animal = cat;
 
Sin embargo, hasta antes del Framework 4.0, una instrucción como esta sacaría error. A partir del Framework 4.0, es posible realizar la asignación, haciendo un cambio mínimo en la declaración del delegado. En particular, se requiere usar la palabra clave out, así:
 
delegate T Func1<out T>();
 
De esta forma, se puede lograr la asignación que hasta antes del Framework 4.0 no era posible y que se conoce como covarianza.
 
Ejemplo:
 
class Animal { }   

class Cat: Animal { }  

class Program    {    

delegate T Func1<out T>();      

static void Main(string[] args)      {          

   // Covariance           

   Func1<Cat> cat = () => new Cat();           

   Func1<Animal> animal = cat;           

}

}
 
La contravarianza tiende a ser más complicada de ilustrar. Aquí, se trata de sustituir el tipo derivado por el tipo base. Una de las situaciones donde a partir del Framework 4, se permite esta sustitución es en el paso de parámetros. La contravarianza se permite es en el paso de parámetros a diferencia de la covarianza que se permite en el retorno de tipos.
 
Ejemplo:
 
class Animal { }   

class Cat: Animal { }   

class Program    {     

delegate void Action1<in T>(T a);      

static void Main(string[] args)      {           

    // Contravariance           

             Action1<Animal> act1 = (ani) => { Console.WriteLine

                             (ani); };           

              Action1<Cat> cat1 = act1;           

           }
 
}
 
De nuevo, debido a que un Gato es un Animal, es esperable y deseable que los delegados que reciben parámetros de tipo Animal se puedan asignar a delegados que reciben Gatos como parámetro.
 
También, es posible, en Enumerados, utilizar las palabras in y out, en su definición, para lograr implementaciones de covarianza y contravarianza respectivamente. De hecho, en el Framework 4.0, ya la definición de la clase Enumerable<T> se modifica por Enumerable<Out T> y, por tanto, podemos tener este código:
 
IEnumerable<Cat> cats = new List<Cat>();
IEnumerable<Animal> animals = cats;
 
Es decir, podemos tener una covarianza, a nivel de enumerados.
 
De nuevo, esto es lo esperable y deseable, ya que como un Gato es un Animal se espera que un enumerado de gatos sea un enumerado de animales.
 
Otra forma de entender los conceptos de porque se llamarón covarianza y contravarianza, es dibujar flechas y asumir que la dirección de la flecha es la dirección del movimiento. Así:
 
En herencia tenemos una conversión de referencia implícita de Animal a Gato:
 
Animal → Gato
 
Y, como vimos, anteriormente, se permite en los enumerados, tener también un conversión de referencia implícita de IEnumerable<Animal> a IEnumerable<Gato>:
 
IEnumerable<Animal> → IEnumerable<Gato>
 
Se llama covarianza porque las flechas apuntan en la misma dirección o siguen el mismo movimiento.
 
En la contravarianza, la flecha va en el sentido contrario:
 
Animal → Gato
IComparable<Animal> ← IComparable<Gato>
 
En términos generales, se puede concluir que la covarianza y la contravarianza se refieren al uso de las palabras reservadas out e in respectivamente, en interfaces genéricas y delegados, para establecer relaciones entre tipos que mantienen la misma conversión de referencia implícita, que los tipos originales tenían en una relación de herencia (covarianza) o donde dicha conversión va en sentido inverso (contravarianza).

miércoles, 16 de marzo de 2011

Dynamics en C#

 

Woow estuve leyendo acerca de las nuevas características que tiene C# para la versión 4 del Framework y me pareció excelente la inclusión de la palabra clave dynamic.
 
Esto permite, postergar, hasta el tiempo de ejecución , la evaluación de tipos. Es decir, en tiempo de compilación no se detectan errores de asignación de tipos.
 
La palabra dynamic permite indicarle al compilador que no efectúe la comprobación de asignación de tipos.
 
En el artículo que se encuentra aca:
http://msdn.microsoft.com/en-us/magazine/gg598922.aspx
 
Se hace una diferenciación clara de lo que son las definiciones con: object, var y dynamic.
 
var: Permite inferir el tipo, pero si hay un error en la asignación de tipos, el compilador lo detecta.
object: Tipo básico de todos los objetos de .NET siempre es necesario efectuar Cast, para hacer la asignación de tipos y que no se genere error en tiempo de compilación.
dynamic: Permite postergar la detección de errores por asignación de tipos hasta el tiempo de ejecución. En tiempo de compilación no se reportan errores.
 
Desde mi punto de vista de desarrollador y relacionado a lo que, normalmente, trabajo. Lo que más me gustó, en cuanto al uso de dynamic, es en los siguientes escenarios:
 
Interoperación con otros lenguajes o frameworks
 
Sin dynamic se tendría que acceder a la característica de Reflexión, para poder acceder a los métodos de un objeto o assembly, con el que se desee interactuar.
 
Ejemplo:
 
1.  object calc = GetCalculator();
2.  Type calcType = calc.GetType();
3.  object res = calcType.InvokeMember(
4.    "Add", BindingFlags.InvokeMethod,
5.    null, new object[] { 10, 20 });
6.  int sum = Convert.ToInt32(res);


Usando dynamic es más simple y fácil de comprender el código:
 
dynamic calc = GetCalculator();int sum = calc.Add(10, 20);
Agregar métodos dinámicamente a objetos
 
1.  dynamic expando = new ExpandoObject();2.  expando.SampleProperty = 3.    "This property was added at run time";4.  expando.SampleMethod = (Action)(5.    () => Console.WriteLine(expando.SampleProperty));6.  expando.SampleMethod();Interoperar con COM
 
Es decir, poder interoperar de una forma más fácil con Office, esta fue la meta de Microsoft al extender C# con dynamic y, en general, el framework DLR ( Dynamic Languaje Runtime)
 
Ejemplo:
 
1.  // Add this line to the beginning of the file:

2.  // using Excel = Microsoft.Office.Interop.Excel;

3.  

4.  var excelApp = new Excel.Application();

5.  

6.  excelApp.Workbooks.Add();

7.  // excelApp.Workbooks.Add(Type.Missing);

8.  

9.  excelApp.Visible = true;

10.

11.Excel.Range targetRange = excelApp.Range["A1"];

12.// Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);

13.

14.targetRange.Value = "Name";

15.// targetRange.set_Value(Type.Missing, "Name");

16.

17.targetRange.Columns[1].AutoFit();

18.// ((Excel.Range)targetRange.Columns[1, Type.Missing]).AutoFit();

En comentarios se encuentra la forma como se tenía que escribir, antes, el mismo código. La facilidad y mejora son innegables.