Diferencia entre ADO Entity Framework Dec CTP y Beta 3

|

Ayer estuve ayudando con una migración de un proyecto que estaba construido con Visual Studio Team Suite 2008 a la version final, pero claro hay que acordarse que EF (ADO Entity Framework) aun esta en Beta 3 y en unos meses saldra su version final, el proyecto en mencion hace un uso bastante intensivo de LinQ y EF, lo cual me agrada mucho, pues bien al pasar lo primero que notamos es que el dbml que contenia el mapeo de entidades a clases estaba en unicode, y debia esta en ANSI, en lenguaje comun hay que cambiar en la cabecera la codificacion de utf-16 a utf-8, lo guardas lo cierras y se abre normalmente...
Ademas en la generacion de las clases resulta que en la entidad como tal el metodo Add, que podia ser usado para agregar entidades, ya no es publico, solo puede ser usado internamente, en su defecto pueden usar Insert o InsertOnSubmit, el segundo es mas facil de usar y si usaron Add antes pueden solo hacer un reemplazo simple sin cambiar parametros, pero cuidado se cambie por el Add que existe en los designers que eso si les puede causar problemas...

Mi conclucion es que el paso de Beta 2 a RTM en Visual 2008 fue 99% limpio, solo con Entity Framework tuvimos un poco de problemas pero nada que definitivamente sea un impedimento mayor...

Problemas de eficiencia usando WCF 3.0?? Aqui esta la solución!!

|

Justo antes de que salga como RTM WCF y el Framework 3.0 tome la decision de usarlo para un proyecto que estaba como hecho para que se use WCF y cabia justo en la dimension de tiempo para que funcione todo en lo correcto, pues bien cuando ya estuvo en produccion a veces mi proyecto no era muy rapido, asi es que comence a indagar que sucedia, al tener por backend Oracle 10g y con un poco de mala experiencia con esa base de datos (debes realmente tener un dba para que funcione como debe y cuando escribes SQL pues tienes que tener un cuidado aun mayor por que si lo escribes solo por escribir seguramente sera lento), por esto pase un par de meses monitoreando la base y afinando mis sentencias, esto definitivamente mejoro el rendimiento en casi todos los procesos, asi es que primera leccion aprendida: Si usas Oracle como backend tambien asegurate de tener un experimentado dba que acompañe todo el desarrollo y la puesta en producción...
Ahi no termina la historia, comenzo a crecer el sistema y mucho mas de lo planeado y volvio a ponerse lento, y mas lento, y mas lento!!! Si bien los usuarios no tenian mucho problema con la lentitud por que la interfase de usuario es asincronica, la verdad yo veia que tenia cada vez mas problemas con la velocidad, ciertos procesos internos realmente tomaban demasiado tiempo, nuevamente entre a buscar el problema, mucho debug del codigo no ayudaba mucho asi es que tenia que probar tecnicas de profile, un producto que me ayudo en verdad es el ANTS profiles de RedGate (http://www.red-gate.com/products/ANTS_Profiler/index.htm) en mi opinion cualquier desarrollador profesional deberia tener una herramienta como esta, ayudo mucho y mas que nada encontre algunas cosas interesantes:

1. Cuando habia comunicacion entre el Cliente WCF y el Servidor WCF el consumo de memoria era realmente un problema, especialmente mi servicio el cual comenzaba a crecer y no dejaba de hacerlo, e incluso nunca liberaba memoria, asi este inactivo algunos días, lo cual me tenia confundido, incluso revisaba con el profiler la memoria, como estaba actuando el GC y cosas relacionadas lo que encontre es que habian millones de objetos de tipo String que no se morían, eso era raro por cuanto yo apenas si usaba un par de constantes dentro del servicio, no ocupaban tanta memoria pero estaban ahi...

2. Despues aisle la funcionalidad del servicio y lo separe en 2, con lo cual pude analizar mejor, resulta que tenia 2 servicios, A y B, donde A era la cara para los programas clientes y a su vez era cliente de B, y B servia como una capa de persistencia, saben que fue lo importante, solo los programas que actuaban como clientes WCF crecian mucho en memoria, el servicio B no pasaba de los 150MB mientras el servicio A llegaba a los 2GB, como es un servidor 32 bits se moria el servicio por su puesto con un System.OutOfMemoryException, esto claro afectaba la disponibilidad del servicio...

Bien al parecer encontre un patron, iba entonces en busqueda de que era exactamente, busque en foros pero nadie tenia un problema similar, estaba casi por rendirme cuando despues de algunos meses note algo extraño: tenia una laptop nueva con Windows Vista y un beta de Visual Studio 2008, en esa maquina funcionaba mucho mas rapido el cliente y no comia tanta memoria, cual era la diferencia?? En un principio pense que era que Vista al tener el Framework 3.0 como parte del sistema operativo esto hacia que WCF sea mas eficiente, pero habia otro cliente Vista que estaba en un punto mas bien intermedio, un tanto rapido pero normalmente lento, descartando todo tipo de problemas de comunicaciones y hardware, resulta que habia una cosa que no habia tomado en cuenta, el Framework 3.5....

Pero que tenia este que comenzaba a notar mejoría?? Un prerequisito importante, los Service Packs 1 de los Frameworks 2.0 y 3.0!!! Y por si acaso tambien el Framework 3.5 tiene un Garbage Collector nuevo y mejorado!! Investigando un poco mas encontre los Knowledge Base de dichos Service Packs (2.0 http://support.microsoft.com/kb/945757, 3.0 http://support.microsoft.com/kb/945826) y pues ni modo me los lei todo para ver que tanto podian afectar a mi software, pero habia estado probando inconcientemente en el cliente Vista con Framework 3.5 beta, y todo funcionaba ok, asi es que hice un par de pruebas mas y comence a desplegar el Framework 3.5 pero el RTM, tanto en el Servidor como en los clientes, el resultado?? Una espectacular mejora en los tiempos de respuesta, al fin vi mi problema resuelto!!!

Ahora tengan cuidado con el SP1 de Framework 2.0 por que si cambia algunas cosas, si deciden dar el paso pues ejecuten abosultamente todas las pruebas del software de nuevo con Service Pack puesto asi despues no tendran sorpresas de tipo mi codigo no funciona o estaba funcionando y ahora ya no....

Espero que esto les de algo de orientación, a mi me costo meses lidiar con este problema...

Entendiendo las Expresiones Lambda al Fin!!!

|

Con la aparición del .NET Framework 3.5 se han estado promocionando algunas de las nuevas caracteristicas de los lenguajes como por ejemplo en C# 3.0 y VB 9.0 las expresiones Lambda, la verdad la primera vez que las vi resulta que no entendi nada!! Funcionaban de un modo magico!!
Me intereso mucho entender como es que funcionan, asi es que investigando un poco resulta que no es nada magico en verdad, simplemente es un uso inteligente de algunas caracteristicas de los lenguages .NET, y voy a tratar de mostrarselos:

1. Una expresion Lambda es un metodo anonimo que puede ser usado para crear delegados o arboles de expresiones

2. Un metodo anonimo es una porcion de codigo que puede ser creada para ser usada como un delegado, a pesar de que es un metodo no es necesario declararlo, es por esto que se lo llama anonimo, esto no es nuevo viene desde C# 2.0, un link interesante para entender mejor es sobre esto es el siguiente: http://msdn.microsoft.com/msdnmag/issues/06/00/C20/default.aspx

3. Un delegado es lo que antiguamente se conocia como un puntero a una funcion, cuando necesitas pasar una funcion como un parametros es muy util, mas informacion?? Encuentrala aqui: http://msdn2.microsoft.com/en-us/library/ms173171(VS.80).aspx

4. Arbol de expresiones: quien no ha construido esto en la Universidad!! Es un tipico arbol para evaluar expresiones, claro la gente de MS lo vuelve un poco mas completo al tema y lo usa como base para cosas muy interesantes, mas informacion: http://www.interact-sw.co.uk/iangblog/2005/09/30/expressiontrees

Bien ahora que tenemos mas claros los conceptos que se usan, podemos hacer la comparacion que a mi me funciono para entenderlo correctamente:

Partiendo del concepto de que una expresion Lambda es una funcion anonima, pero con una notacion diferente, podemos entonces entender que tiene parametros de entrada y devuelve un valor, vamos bien, pero cual es la notacion correcta?? Este articulo me guio hacia la luz!!
http://www.hanselman.com/blog/TheWeeklySourceCode13FibonacciEdition.aspx

Y de ahi tomare prestado el ejemplo de las funciones para compararlos y explicarlos:

C# 2.0
static int Fibonacci (int x)
{
if (x <= 1) return 1; return Fibonacci (x-1) + Fibonacci (x-2); } C# 3.0 (Hace falta referenciar System.Core y System.Func) Func fib = null;
fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;

Como ven estas funciones nos ayudan con la famosa serie de Fibonaccim y las 2 funcionan muy pero muy bien, claro vamos ha hacer las relaciones correspondientes para que vean que son lo mismo:

Declaracion y Parametros de entrada

C# 2.0: La tipica declaracion de la funcion en la primera linea:
static int Fibonacci (int x)

Funcion estatica llamada Fibonacci, tiene un parametro de entradad de tipo int (int en C#, Int32 para el FCL, Integer para VB) y devuelve un resultado de tipo int (lo mismo que el parentesis anterior)

C# 3.0:
Parte de la segunda linea
fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;

Como estan pensando, solo n es la declaracion de la funcion, donde n es el parametro de entrada, pueden haber mas de un parametro de entrada, en este caso no es necesario, y se preguntaran: Y los tipos del parametro y el tipo del resultado de la funcion?? Esta es la parte interesante, aqui se usa una caracterista nueva que se llama inferencia de tipos, cuando la expresion lambda esta completa y bien escrita el compilador puede inferir los tipos que se usan, como se imaginaran entonces para que una expresion lambda funcione como nosotros deseamos debemos tener cuidado como escribimos el cuerpo de la misma, por cuanto el inferir el tipo no es tan sencillo como se piensa... Y el nombre de la funcion?? Como es un metodo anonimo no le hace falta la verdad, internamente se le asigna un nombre automaticamente para poder referenciarlo...

Cuerpo de la funcion e instrucciones

C# 2.0: lineas 2, 3, 4, 5 y 6

{
if (x <= 1) return 1; return Fibonacci (x-1) + Fibonacci (x-2); } Delimitan la funcion las llaves en la linea 2 y 6, dentro tenemos un if que verifica que el parametro no este fuera del rago y si lo esta devuelve un valor por default (1), si no hace un calculo simple basado en recursividad para ser devuelvo con una sentencia return, nada dificil verdad?? C# 3.0: Otra vez parte de la segunda linea fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;

Muy bien aqui lo que hace es con el operador ?: (si no le conocen mucho a este operador entonces vayan a http://fcolomas.blogspot.com/2007/12/el-gourmet-net-que-es-mas-eficiente-un.html) reemplazar la funcionalidad del if y la linea del return de la funcion c# 2.0, es decir si n que es el parametro de entrada declarado antes es mayor que 1 entonces usa la recursividad para llamar de nuevo a la funcion y ejecutar un calculo simple, de lo contrario el valor que se devuelve es n.

Supongo que aun tienen preguntas, voy a aclarar algunas cosas que a mi me saltarian como dudas:

1. Que es esto de la linea 1 del la funcion en C# 3.0??
Resulta que como la expresion lambda es un metodo anonimo (puede tambien ser llamado funcion anonima) y como voy a requerir usarlo recursivamente de algun modo debo poder volver a llamarlo!! Recuerden que un metodo anonimo no tiene nombre, entonces como lo vuelvo a usar?? Justamente con el tipo Func uno puede almacenar esta referencia es por eso que se declara Func fib = null; con lo cual se reserva espacio para la referencia a la funcion, claro con esto tambien ya le damos las pistas necesarias al compilador para que luego la expresion lambda que va a ser almacenada tenga los tipos correctos tanto para los parametros como para el resultado...

2. Y el operador => que significa??
Este es la separacion de la expresion, con esta se sabe que el lado izquierdo contiene los parametros y el lado derecho las instrucciones, ahora si desean ejecutar mas instrucciones claro que se puede, al lado derecho ponen un par de llaves y dentro las instrucciones tal cual una funcion y voila!!

Esas dos son las mas notorias a mi modo de ver, ahora si ustedes tienen mas preguntas pues con todo gusto!!!

Algunos links utiles:

Expresiones Lambda para VB
http://msdn.microsoft.com/msdnmag/issues/07/09/BasicInstincts/default.aspx

Expresiones Lambda para C# desde MSDN
http://msdn2.microsoft.com/en-us/library/bb397687.aspx