Los 4 Jinetes del Apocalipsis

No os preocupéis, que aunque me estoy pasando al lado oscuro aún no he perdido la cabeza, no quiero hablar de “caballo blanco”,”caballo rojo”,”caballo negro” y “caballo bayo”. En esta ocasión voy a hablar de otros 4 jinetes que pueden hacer de nuestro código una apocalipsis. Me refiero concretamente a estos 4 “this”,”call”, ”apply” y “bind” de quien?

De quien va a ser, de mis últimas andadas por “Javascript”. Bueno vamos al grano:).

this: Sobre este hay ríos de tinta, pero voy a intentar explicarlo desde una lógica. Cuando nosotros definimos una función tal como esta.

console.log(window.name);
function foo(name) {
this.name = name;
}
console.log(window.name);

Y la invocamos como foo(‘window’). Lo que realmente estamos haciendo es llamar a un método que hemos definido en el objeto window (ámbito global) y agregando a  este sino lo tiene una propiedad con nombre “name”, no es el caso puesto que window ya posee una propiedad llamada “name”.
 
En realidad tiene todo el sentido del mundo foo pertenece a window y por tanto this es window. para comprobarlo podéis ejecutar
 
“foo” in window y devuelve true.
 
¿Cuándo this es foo ? pues cuando hacemos lo siguiente:
 
window.name = "window";
function foo(name) {
this.name = name;
}
var objeto = new foo("mi nombre");
console.log(window.name);
console.log(objeto.name);
 
La salida en este caso es “window” para window.name y “mi nombre” para “objeto.name”. Lo que hemos hecho no es invocar un método sino crear un objeto del tipo foo y por tanto this es el y no el ámbito global.
 
Vamos ahora a definir un objeto y vemos que su comportamiento es exactamente el mismo.
 
objeto = {
name: "",
surname: "",
fullname: function () {
console.log(this.name + " " + this.surname);
}
}
objeto.name = "Pedro";
objeto.surname = "Hurtado";
objeto.fullname();
 
Ya podemos decir que “this” se comporta de la forma esperada “this representa el objeto al que pertenece nuestro método o propiedad”  no cambia respecto a lo que estamos acostumbrados.
 
Pero claro en este fantástico lenguaje “de verdad”, siempre tiene que haber una excepción y la excepción es “this entra en el limbo”. 
 
Vamos con un ejemplo.
 
window.name = "window";
function foo(name,surname){
this.name = name;
this.surname = surname;
this.fullname = function () {
function writeFullName() {
console.log(this.name + " " + this.surname);
}
writeFullName();
}
}

var objeto = new foo("Pedro", "Hurtado");
objeto.fullname();
 
En este caso alguno puede pensar que la salida por consola será “Pedro Hurtado”, pues no this se fue al limbo y la salida es “window undefined”. Y si antes dijimos que “this representa al objeto al que pertenece el método o propiedad”
 
¿A quien pertenece WriteFullName?.
 
Mis ojos me dicen que a nadie es algo raro, esta en el limbo:). Bueno señores ese limbo no es otro que el objeto global “window”.
 
Y alguien puede decir menuda ….. No por favor!!!. Vienen a salvarnos los otros tres jinetes.
 
call: Realmente es un método del objeto “Function” si “F” con mayúscula y nos permite invocar a una función pasando en el primer parámetro el ámbito es decir this y en el segundo parámetro una lista de los posibles parámetros separados por comas, yo en este caso no lo estoy utilizando, una de las bondades o maldades del dinamismo .
 
 
window.name = "window";
function foo(name,surname){
this.name = name;
this.surname = surname;
this.fullname = function () {
function writeFullName() {
console.log(this.name + " " + this.surname);
}
writeFullName.call(this);
}
}
var objeto = new foo("Pedro", "Hurtado");
objeto.fullname();
Ahora si que el resultado es el esperado, por consola la salida será “Pedro Hurtado”.
 
apply: De este poco que decir una vez explicado que hace call. La única diferencia es que el segundo parámetro se pasa como una array. La verdad que no se cual fue primero si call o apply pero realmente son el mismo perro con distinto collar:).
 
bind: Tratemos al último jinete este a diferencia call y apply lo que hace es establecer el ámbito y si se quiere los parámetros pero no invoca a la función. Es decir devuelve un objeto que después podemos invocar.
 
Como podemos observar los metodos “call”, “apply” y “bind” tiene un comportamiento parecido y lo que vienen es a suplir  la carencia real de javascript de no tener bien resuelto el funcionamiento de this.
 
Con lo cual tenemos que tener mucho cuidado con el uso de this en los callback que tan de moda se han puesto. Si por ejemplo observáis código WinJs se puede ver que casi siempre que se ejecuta algún Promise y queremos tratar con this nos encontramos con bind.
 
Lo que realmente hace falta desde mi punto de vista es ya de una vez, alguna palabra reservada como “class”  y su funcionamiento lógicamente implementado. Si las fuentes no me fallan creo que estamos en el camino http://wiki.ecmascript.org/doku.php?id=harmony:classes, pero claro seguro que protected override o alguna otra la dejan para la versión no harmony sino para la versión ecma-apocalypse.
 
Conclusiones.
 
De lo más sencillo, evita el uso de this en javascript. No solo te puedes llevar sorpresas sino que además vas a definir variables innecesarias en el ámbito global, si después de esto sigues empeñado en el uso de this, acuérdate de usar si lo necesitas los otros tres jinetes.

Soy asincrono despues de 0 milisegundos

Posiblemente alguno  puede seguir pensando que escribir un Promise es hacer su código Javascript asíncrono. Bueno pues si piensas eso ya te digo yo que no.

Promise no es más que un mecanismo para hacer nuestro código más legible y de esa forma evitar los tediosos callback que hasta el momento hemos utilizado.

Bueno como siempre vamos a empezar con un ejemplo para demostrar que Promise no es asíncrono.

function promise() {
return new WinJS.Promise(function (complete, error, progress) {
try {
var i = 0;
for (i = 0; i < 10; i++) {
progress(i);
}
complete(i);
}
catch (ex) {
error(ex);
}
});
}
function runPromise() {
var result = promise().then(
function (data) {
console.log(data);
},
function (progress) {
console.log(progress);
},
function (error) {
console.log(error);
});

}
runPromise();
Si analizamos este código la respuesta inmediata sería, la salida por consola nos mostrará  la siguiente secuencia 0,1,2,3,4,5,6,7,8,9 y por último 10. La respuesta es por consola solamente vamos a ver “10”, es decir la ejecución de complete, pero nunca progress.
 
Ante esto la pregunta  ¿Si progress se ejecuta y no es “undefined”, porque no escribe en la consola el valor de i?. Pues sencillo o creo que más bien complicado:).
 
Cuando ejecutamos el constructor de una Promise pasan varias cosas.
 
1. Se pasa al contructor una función anónima que recibe tres parámetros “complete,error,progress” y se ejecuta.
 
2. Ninguno de los tres parametros apunta en realidad a las funciones que he pasado como parametros  a la función then. Puesto que aún no se ha ejecutado, sino a “complete,error,progress” de “PromiseStateMachine” una clase que se crea en base.js de la que deriva “Promise”.
 
3. ¿Y por qué se ejecuta “complete” y no “progress”? Pues por eso por que Javascript es “single-threaded”. Realmente la línea de código siguiente “complete(i)” no hace lo que creemos , sino asignar un valor “10”  al objeto Promise que hemos creado.
 
4. Bueno ¿Y entonces porque ejecuta lo siguiente?
 
function (data) {
console.log(data);
},
 
Porque al ejecutar “then” después de nuestra función anónima nuestra Promise ha realizado internamente lo suficiente como para que “then” sea un objeto del tipo “CompletePromise” y llama a la función “then” de este, ¿queréis ver  el código? 🙂
 
try {
// If the value returned from the completion handler is the same as the value
// provided to the completion handler then there is no need for a new promise.
//
var newValue = onComplete ? onComplete(this._value) : this._value;
return newValue === this._value ? this : new CompletePromise(newValue);
} catch (ex) {
return new ExceptionPromise(ex);
}

En la primera linea se ve claramente que se llama a “onComplete”,  función que escribe en la consola nuestro famoso “10”. De lo cual podemos deducir que primero se ejecuta nuestro bucle y después “then”, sino os convence podéis cambiar el valor 10 por 100000000 y ya os digo yo que os vais a esperar un poquito o más bien mucho:).
 
Bueno después de este tedioso rollo, quizá alguien se pregunte para que quiero utilizar Promise, bueno mi conclusión es sencilla como dije nos ayuda a estructurar nuestro código de mejor forma, cosa que no implica que mi código sea asíncrono. Queda claro no:).
 
Queréis el mismo código asíncrono, entre comillas:), bueno pues otra función anónima que ejecute nuestro bucle pero con “setTimeout”.
 
function promise() {
return new WinJS.Promise(function (complete, error, progress) {
var id;
id = setTimeout(function () {
try{
for (var i = 0; i < 10; i++) {
progress(i);
}
complete(i);
}
catch (ex) {
error(ex);
}
finally {
if (id) {
clearTimeout(id);
}
}
}, 0);
});
}
function runPromise() {
promise().then(
function (data) { console.log(data); },
function (progress) { console.log(progress); },
function (error) { console.log(error); }
);
}
runPromise();

Y a estás alturas alguien puede pensar y porque el titulo de este post, pues porque por casualidades de la vida ayer me encontré con esta otra entrada que es digna de leer y yo paso un 0 a setTiemout:).

setImediate Api

Me tome la molestia de escribir este script y probarlo en Chrome,FireFox e IE9 y la verdad que me sorprendió, bastante que Chrome sea el más lento en ejecutar callback por segundosSonrisa

var i = 0,
id,
endDate,
startDate = new Date().getTime(),
ckeckEnd = function () {
endDate = new Date().getTime();
var result = (endDate - startDate)
if (result >= 1000) {
if (id) clearInterval(id)
console.log(result + " " + i);

}
else {
i++;
}

};
id = setInterval(function () {
ckeckEnd();
}, 1);

Conclusion:

Que todo esto es un mundo desconocido para los que venimos de c# y que realmente explorarlo es toda una satisfacción, aunque podemos decir que Javascript tiene mucho, pero mucho que mejorarSonrisa

 

Ocultar o esconder no es prohibir

Si me pongo a pensar y me traslado al pasado, siempre hable mal de Javascript. Últimamente he cambiado mi actitud pero con peros, es decir es un lenguaje que tiene que mejorar y no poco:).

Revisando WinJS, de esa forma que me gusta a mí. No haciendo el típico ejemplo “Hola Mundo”, sino adentrándome en las profundidades de “base.js” me encuentro con lo siguiente:

function initializeProperties(target, members) {
var keys = Object.keys(members);
var properties;
var i, len;
for (i = 0, len = keys.length; i < len; i++) {
var key = keys[i];
var enumerable = key.charCodeAt(0) !== /*_*/95;
var member = members[key];
if (member && typeof member === 'object') {
if (member.value !== undefined || typeof member.get === 'function' || typeof member.set === 'function') {
if (member.enumerable === undefined) {
member.enumerable = enumerable;
}
properties = properties || {};
properties[key] = member;
continue;
}
}
if (!enumerable) {
properties = properties || {};
properties[key] = { value: member, enumerable: enumerable, configurable: true, writable: true }
continue;
}
target[key] = member;
}
if (properties) {
Object.defineProperties(target, properties);
}
}
 

La verdad que tampoco me adentre mucho, puesto que esto te lo encuentras entre las líneas 15 y 46 de base.js.

Lo que más me llamo la atención fue concretamente esta línea

“var enumerable = key.charCodeAt(0)!== /*_*/ 95;

En realidad eso lo que hace es comprobar, como bien podéis ver si el primer carácter de una propiedad empieza por “_” y marcar enumerable como false.

¿Que es enumerable?

Pues sencillo uno de los parametros del objeto que pasamos en el tercer de los parametros a Object.defineProperty. Seguro que alguno se estará preguntado si esto significa que esa propiedad es privada por aquello de “_” , bueno eso no es así. Realmente lo que hace es ocultar esta propiedad a los siguientes métodos, entre otros:

1. Object.Keys(objecto);

2. for (prop in objecto)

Por contra  esa propiedad será accesible si accedemos a ella de la siguiente forma:

1. objeto._propiedad.

2. objecto[“_propiedad”]

3. “_propiedad” in objeto devuelve true;

Os paso el siguiente script por si alguien quiere conprobarlo.

var objeto = {};
Object.defineProperty(objeto, "_propiedad", { value: 10, enumerable: false, writable: true, configurable: true });
for (var propiedad in objeto) {
console.log(propiedad);
}
objeto["_propiedad"] = 20;
console.log(objeto["_propiedad"]);
console.log(objeto._propiedad);
console.log("_propiedad" in objeto);

Que hace por nosotros Visual Studio a nivel de Intellisense. Pues sencillo ocultar cualquier propiedad de un objeto javascript cuyo nombre empiece por “_”. Eso es bueno, pues para quien lo quiera quizá sí, para mí ya os digo que no, puesto que en el fondo esa propiedad es tan publica como cualquier otra.

De eso es fácil deducir  que cualquier objeto creado en WinJS con los métodos

WinJS.Namespace y WinJS.Class expone todas sus propiedades como públicas.

La pregunta a esto es sencilla ¿a quien le gusta esto?.

Como referencias os paso los siguientes link.

http://msdn.microsoft.com/es-es/library/kb6te8d3(v=vs.94).aspx

http://msdn.microsoft.com/es-es/library/hh965578(v=vs.94).aspx

http://kangax.github.com/es5-compat-table/#showold

Veis como Ocultar no es Prohibir Sonrisa.

Desmitificando CodeFirst(2/2) V 4.3

En el anterior post Desmitificando CodeFirst(1/2), me he centrado en la versión 4.2 de Entity Framework y el objetivo de este no es otro que analizar la versión 4.3 y ver realmente que hay en la tabla “dbo.__MigrationHistory”.

Siguiente con el modelo anterior lo primero que tenemos que hacer es activar Migration, pero como no es el objetivo de este post os paso un link para quien no lo conozca y quiera profundizar.

EF 4.3 Automatic Migrations Walkthrough.

El objetivo claro es demostrar dos cosas.

1. Lo que se guarda en la tabla no es un Hash sino un Xml, eso si con aderezo:).

2. Ver lo parco que es EF en la gestión de Exceptions teniendo a mano toda la información para mostrarnos algo más que lo que nos dice.

Vamos con lo primero. Para ello no necesitamos nada más que leer con Ado.Net la tabla “dbo.__MigrationHistory” y descomprimir el contenido de la columna Model.

   1: using (SqlConnection cn = new SqlConnection(@"Tu Conexion"))

   2:  {

   3:      cn.Open();

   4:  

   5:      SqlCommand cmd = new SqlCommand("select top 1 Model from dbo.__MigrationHistory order by CreatedOn desc", cn);

   6:      SqlDataReader rd = cmd.ExecuteReader();

   7:      rd.Read();

   8:      byte[] b = rd[0] as byte[];

   9:  

  10:      using (MemoryStream ms = new MemoryStream(b))

  11:      {

  12:          using (GZipStream stream2 = new GZipStream(ms, CompressionMode.Decompress))

  13:          {

  14:              var Edmx = XDocument.Load(stream2);

  15:              Console.WriteLine(Edmx.ToString());

  16:          }

  17:  

  18:      }    

  19:      

  20:  

  21:  

  22:  }

  23:  

  24:  Console.ReadLine();

Con lo cual si el XDocument lo guardasmos en disco con la extensión edmx y agregamos este al proyecto vemos que es lo que hay en la tabla Migrations.

Dibujo

Ya si nos queda claro que estamos utilizando Xml:)

Vamos a seguir con nuestro querido “InvalidOperationException”. Y concretamente de lo que me quejo es de EF no nos informe de algo más en esta exception, puesto que podría decirnos exactamente que es lo que cambia entre un modelo y otro.

Para ello seguimos con la operación del anterior post y cambiamos  la longitud de la propiedad Nombre de 50 a 100 y obtenemos la misma exceptión pero con un mensaje diferente.

Dibujo

Claro lo fácil sería ejecutar los siguiente comandos desde Pakage Manager Console

1. Enable-Migrations.

2. Add-Migration "Salvameporfavor"

3. Update-Database –Verbose.

Y todos felices, pero se puede dar el caso que no me interese modificar la base de datos sino simplemente saber el porque y en consecuencia actuar. Para ello vamos de nuevo con Reflectión y ver que hace internamente EF para mostrarnos esta exceptión. En definitiva lo que hace es comparar el modelo guardado con el modelo generado.

El código para obtener las diferencias es el siguiente y después de mostrarlo vendrás las criticas, eso si constructivas:)

   1: XDocument documentDataBase = null;

   2:  

   3: using (SqlConnection cn = new SqlConnection(@"Tu Cadena de Conexion"))

   4: {

   5:     cn.Open();

   6:  

   7:     SqlCommand cmd = new SqlCommand("select top 1 Model from dbo.__MigrationHistory order by CreatedOn desc", cn);

   8:     SqlDataReader rd = cmd.ExecuteReader();

   9:     rd.Read();

  10:     byte[] b = rd[0] as byte[];

  11:     using (MemoryStream ms = new MemoryStream(b))

  12:     {

  13:         using (GZipStream stream2 = new GZipStream(ms, CompressionMode.Decompress))

  14:         {

  15:             documentDataBase = XDocument.Load(stream2);

  16:         }

  17:  

  18:     }       

  19:  

  20:  

  21: }

  22:  

  23: XDocument documentModel = null;

  24: using (ContextCliente ct = new ContextCliente())

  25: {

  26:     using (MemoryStream stream = new MemoryStream())

  27:     {

  28:         XmlWriterSettings settings = new XmlWriterSettings();

  29:         settings.Indent = true;

  30:         using (XmlWriter writer = XmlWriter.Create(stream, settings))

  31:         {

  32:             EdmxWriter.WriteEdmx(ct, writer);

  33:  

  34:         }

  35:         stream.Position = 0L;

  36:         documentModel = XDocument.Load(stream);

  37:     }

  38:  

  39:  

  40: }

  41:  

  42:  

  43: Assembly a = typeof(DbContext).Assembly;

  44:  

  45: var tipo = a.GetTypes().Where(c => c.FullName == "System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer").FirstOrDefault();

  46:  

  47: var ModelDiffer = Activator.CreateInstance(tipo);

  48:  

  49: var Metodo = ModelDiffer.GetType().GetMethod("Diff");

  50:  

  51: var resultado = Metodo.Invoke(ModelDiffer, new object[] { documentDataBase, documentModel, null });

Si miramos el código estamos llamando al metodo “Diff” de la clase “System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer”. Como no, definida con el modificador de acceso “Internal” 🙁 y este nos devuelve un IEnumerable<MigrationOperation> y en nuestro caso una clase derivada de MigrationOperation con nombre “AlterColumnOperation”, me suena a la migration que queda pendiente de ejecutar en la bb.dd.

Y ahora yo digo en vez de preguntar y devolver bool en el método “ModelMatches” de la clase “InternalContext” por que no se contruye una exception en condiciones diciendo en que difieren ambos modelos, veis como la critica es constructiva:)

ModelMatches de la clase InternalContext".

   1: public virtual bool ModelMatches(XDocument model)

   2: {

   3:     string connectionString = null;

   4:     return !new EdmModelDiffer().Diff(model, this.Owner.GetModel(), connectionString).Any<MigrationOperation>();

   5: }

Pues nada esperemos que alguien piense en ciertas mejoras y que estás nos ayuden a dormir mas felices:)

Desmitificando CodeFirst(1/2)

El día 22 tuve la suerte con @MiguelEgea, de dar una charla en Málaga .NET User Group y una de las cosas que afirme es que la tabla del sistema que se genera con la versión 4.3 “dbo.__MigrationHistory” en su columna “Model” no guarda un Hash sino que realmente es una copia del modelo, es decir un emdx comprimido.

Inmediatamente @pablonete me pone cara de incrédulo y que mejor que demostrarle eso con un post:).

Independientemente de demostrar esto lo primero que quiero desmitificar es que Codefirst utiliza Xml y no poco, en resumen el mismo que las otras dos modalidades DataBaseFirst y ModelFirst.

Lo segundo es que casi todos los que trabajamos con CodeFisrt tarde o temprano recibimos una “InvalidOperationException” tal y como os muestro.

Dibujo

El porque es sencillo tu modelo no coincide con lo que en versión 4.2 tenemos guardado en la tabla “EdmMetadata”.

Y es aquí donde @pablonete si tiene razón en versión 4.2 si se guarda un “Hash” mientras que en 4.3 no.

Vamos a demostrarlo con la versión 4.2.

1. Definimos un modelo sencillo que es valido para el ejemplo.

   1: //Entidad

   2: public class Cliente

   3: {

   4:    public int Id { get; set; }

   5:    public string Nombre { get; set; }

   6: }

   7: //Configuracion de la entidad Cliente

   8: public class ClienteEntityConfiguration : EntityTypeConfiguration<Cliente>

   9: {

  10:    public ClienteEntityConfiguration()

  11:    {

  12:        this.ToTable("Clientes");

  13:        this.HasKey(c => c.Id);

  14:  

  15:        this.Property(c => c.Nombre).HasMaxLength(50).IsRequired();

  16:    }

  17: }

  18: //DbContext

  19: public class ContextCliente : DbContext

  20: {

  21:    protected override void OnModelCreating(DbModelBuilder modelBuilder)

  22:    {

  23:        modelBuilder.Configurations.Add(new ClienteEntityConfiguration());          

  24:  

  25:    }

  26: }

Sí creamos un cliente y posteriormente nos vamos a la bb.dd y ejecutamos “select * from EdmMetadata” el resultado de la consulta es el siguiente.

Dibujo

La forma sencilla de provocar “InvalidOperationException” es cambiar en la clase ClienteEntityConfiguration esta línea

this.Property(c => c.Nombre).HasMaxLength(50).IsRequired();

Por esta otra

this.Property(c => c.Nombre).HasMaxLength(100).IsRequired();

A partir de ese momento nuestro Hash se convierte en lo siguiente.

0F9CDC01973A8E83D521518166B9F8C37E8D533704219CF1F2DC02B83AEE0F77”

El cual podemos obtener con el siguiente código.

   1: using (ContextCliente ct = new ContextCliente())

   2: {                

   3:     var model = EdmMetadata.TryGetModelHash(ct);             

   4: }

A simple vista vemos que hay una diferencia y es por eso el motivo de recibir “InvalidOpertationException”.

Lógicamente se pueden definir estrategias que para mi son peores que recibir la exception.

1. Eliminar la bb.dd cada vez que se hace un cambio, con algo como lo siguiente.

   1: System.Data.Entity.Database.SetInitializer(new DropCreateDatabaseIfModelChanges<ContextCliente>());

2. Eliminar de las conventions “IncludeMetadataConvention” que aún es peor solución puesto que tarde o temprano cantará:).

Como se puede observar en versión 4.2 bastantes cosas desde mi punto de vista mal pensadas, pero bueno eso es parte del pasado y lo mejor como siempre es ser positivos:)

Ahora vamos a demostrar como ese Hash se genera a partir de un Xml y de esa forma eliminar parte del mito “CodeFisrt no utiliza Xml”. Señores síiii:)

Vamos a dejar nuestro ContextCliente de la siguiente forma y utilizar un montón de Reflection para ver lo que se convierte a Hash.

   1: public class ContextCliente : DbContext

   2: {        

   3:     protected override void OnModelCreating(DbModelBuilder modelBuilder)

   4:     {

   5:        

   6:         //Agregamos ClienteEntityConfigurtarion 

   7:         // a modelBuilder.Configuration

   8:         modelBuilder.Configurations.Add(new ClienteEntityConfiguration());

   9:         

  10:         //Obtenemos un DbModel

  11:         var Model = modelBuilder.Build(this.Database.Connection);

  12:     

  13:         //Obtenemos una clase internal

  14:         //Llamada "DbDatabaseMetadataExtensions"

  15:         Type t = (from b in typeof(DbContext).Assembly.GetTypes()

  16:                  where b.Name == "DbDatabaseMetadataExtensions"

  17:                  select b).FirstOrDefault();

  18:     

  19:         //De esa clase el Metodo ToStoreItemCollection

  20:         var Method = (from b in t.GetMethods(BindingFlags.Static | BindingFlags.Public)

  21:                       where b.Name == "ToStoreItemCollection"

  22:                       select b).FirstOrDefault();

  23:     

  24:         //Obtenemos del DbModel la propiedad "DatabaseMapping"

  25:         var DataBaseMappingProperty = Model.GetType().GetProperty("DatabaseMapping", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

  26:     

  27:         var DataBaseMapping = DataBaseMappingProperty.GetValue(Model, null);

  28:         //Obtenemos de DataBaseMapping la propiedad Database

  29:         var DataBaseMetadaProperty = DataBaseMapping.GetType().GetProperty("Database",BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

  30:     

  31:         var DataBase = DataBaseMetadaProperty.GetValue(DataBaseMapping, null);

  32:     

  33:         Action<string> Action = (xml) =>

  34:             {

  35:                 Console.WriteLine(ComputeSha256Hash(xml));                    

  36:             };

  37:         //Invocamos al metodoToStoreItemCollection

  38:         Method.Invoke(DataBase, new object[] { DataBase, Action });

  39:         Console.ReadLine();          

  40:     

  41:     }

  42:     

  43:     static string ComputeSha256Hash(string input)

  44:     {

  45:         byte[] buffer = GetSha256HashAlgorithm().ComputeHash(Encoding.ASCII.GetBytes(input));

  46:         StringBuilder builder = new StringBuilder(buffer.Length * 2);

  47:         foreach (byte num in buffer)

  48:         {

  49:             builder.Append(num.ToString("X2", CultureInfo.InvariantCulture));

  50:         }

  51:         return builder.ToString();

  52:     }

  53:     

  54:     

  55:     

  56:     static SHA256 GetSha256HashAlgorithm()

  57:     {

  58:         try

  59:         {

  60:             return new SHA256CryptoServiceProvider();

  61:         }

  62:         catch (PlatformNotSupportedException)

  63:         {

  64:             return new SHA256Managed();

  65:         }

  66:     }

  67: }

Solo os invito a que pongáis un breakPoint dentro del Action<string>

Dibujo

Y veáis el valor del parametro “xml”. Bueno para los más gandulones os lo muestro yo:)

   1: <?xml version="1.0" encoding="utf-16"?>

   2: <Schema Namespace="CodeFirstDatabaseSchema" Provider="System.Data.SqlClient" ProviderManifestToken="2008" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">

   3:   <EntityType Name="Cliente">

   4:     <Key>

   5:       <PropertyRef Name="Id" />

   6:     </Key>

   7:     <Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />

   8:     <Property Name="Nombre" Type="nvarchar" MaxLength="100" Nullable="false" />

   9:   </EntityType>

  10:   <EntityType Name="EdmMetadata">

  11:     <Key>

  12:       <PropertyRef Name="Id" />

  13:     </Key>

  14:     <Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />

  15:     <Property Name="ModelHash" Type="nvarchar(max)" Nullable="true" />

  16:   </EntityType>

  17:   <EntityContainer Name="CodeFirstDatabase">

  18:     <EntitySet Name="Cliente" EntityType="Self.Cliente" Schema="dbo" Table="Clientes" />

  19:     <EntitySet Name="EdmMetadata" EntityType="Self.EdmMetadata" Schema="dbo" Table="EdmMetadata" />

  20:   </EntityContainer>

  21: </Schema>

Convencidos que el Hash de la versión 4.2 de CodeFirst se genera a partir del xml del Modelo:).

Bueno publico y voy con el segundo en CodeFirst 4.3 no es Hash sino un edmx comprimido.

El respositorio genérico.Un Derrochador en épocas de crisis.

Durante muchos días,semanas,meses e incluso años he visto la siguiente definición de un repositorio.

1. Interface IRepository.

   1: public interface IRepository<T> where T:class

   2: {

   3:    T Get(int Id);

   4:    T Insert(T Entity);

   5:    void Update(T Entity);

   6:    void Delete(T Entity);

   7:    IEnumerable<T> GetAll();

   8:  

   9:    IUnitOfWork UnifOfWork { get;}

  10: }

2. Interface IUnitOfWork

   1: public interface IUnitOfWork

   2: {

   3:     void Commit();

   4:     void RollBack();

   5: }

3. Interface IContext que implementamos en  nuestro contexto de Entity Framework, en ella simplemente voy a definir un método que me devuelva un DbSet<T>

   1: public interface IContext:IUnitOfWork

   2: {

   3:     DbSet<TEntity> CreateSet<TEntity>() where TEntity : class;

   4: }    

El objetivo de este post no es demostrar que evidentemente estamos ligados fuertemente a EF, desde el momento que utilizamos DbSet<T>, sino analizar la interface IRepository.

Para ello voy a crear una clase base o Layer Supertype donde voy a implementar la interface IRepository

   1: public class Repository<T> : IRepository<T> where T:class

   2: {

   3:     readonly IContext _Context;

   4:     readonly IUnitOfWork _UnitOfWork;

   5:     public Repository(IContext Context)

   6:     {

   7:         if (Context == null)

   8:             throw new NullReferenceException("El contexto no puede ser nulo");

   9:  

  10:         _Context = Context;

  11:         _UnitOfWork = Context;

  12:     }

  13:     public T Get(int Id)

  14:     {

  15:         return GetSet().Find(Id);

  16:     }

  17:  

  18:     public T Insert(T Entity)

  19:     {

  20:         throw new NotImplementedException();

  21:     }

  22:  

  23:     public void Update(T Entity)

  24:     {

  25:         throw new NotImplementedException();

  26:     }

  27:  

  28:     public void Delete(T Entity)

  29:     {

  30:         throw new NotImplementedException();

  31:     }

  32:  

  33:     public IEnumerable<T> GetAll()

  34:     {

  35:         return GetSet().AsEnumerable();

  36:     }

  37:  

  38:     public IUnitOfWork UnifOfWork

  39:     {

  40:         get { return _UnitOfWork; }

  41:     }

  42:     private DbSet<T> GetSet()

  43:     {

  44:         return _Context.CreateSet<T>();

  45:     }

  46: }

Como podéis observar los métodos Insert,Update y Delete no están implementados, puesto que como dije anteriormente no es objetivo de este post y aparte tampoco me apetece:).

Vamos a realizar un análisis de esto.

1. Estamos ligados a EF sí y no más comentarios:).

2.La interface IRepository<T> expone métodos que con total seguridad  no necesitemos? Sí.

Un ejemplo sencillo la entidad X no se  puede modificar ni eliminar. Para ello os recomiendo esta lectura que ayer concretamente twitee.

https://twitter.com/_PedroHurtado/status/210311759872000000

3. Si vemos estas pegas y lo seguimos utilizando, porque no le damos una vuelta de tuerca. Para ello os voy a exponer el siguiente requisito y lógicamente no voy a escribir todas las entidades necesarias sino quiero que os lo imaginéis:).

Un Cliente tiene una forma de pago asignada por defecto, para que cuando cree una nueva factura se la asigne a esta. Con no otro objetivo que ayudar al usuario y este lógicamente podrá cambiarla por cada operación, entendido no?

Tal y como hemos creado nuestro repositorio no nos queda otra opción que leer todos los datos del cliente y no son tres campos en la vida real. Para obtener el Id y la Descripción de la forma de pago tenemos que leer todos los datos del cliente y además hacer otra lectura para recuperar el nombre de la forma de pago. Luego nos quejamos que EF es lento o somos nosotros los que lo hacemos lento.

Porque no exponemos nuestro método Get con la siguiente firma

TResult Get<TResult>(int Id,Expression<Func<T,TResult>> Select);

Lo mismo ahora podemos implementar nuestro Get de esta forma

   1: public TResult Get<TResult>(int Id, Expression<Func<T, TResult>> Select)

   2: {

   3:     return GetSet()

   4:             .Where(c => c.Id == Id)

   5:             .Select(Select)

   6:             .FirstOrDefault();

   7: }

y definir un repositorio para la clase Cliente que nos devuelva bien la Entidad Cliente o parte de ella, queréis verlo?

Bueno pues escribimos las clases necesarias para ello y veréis:)

   1: public class Entity

   2: {

   3:    public int Id { get; set; }

   4: }

   5: public class Cliente:Entity

   6: {       

   7:    public string Nombre { get; set; }

   8:    public FormaPago FormaPago { get; set; }

   9: }

  10: public class FormaPago:Entity

  11: {

  12:    public string Nombre { get; set; }

  13: }

  14: public interface IRepositoryCliente : IRepository<Cliente>

  15: {

  16:  

  17: }

  18: public class RepositoryCliente : Repository<Cliente>, IRepositoryCliente

  19: {

  20:    public RepositoryCliente(IContext Context)

  21:        : base(Context)

  22:    {

  23:    }

  24: }

  25:  

  26: public class Contexto : DbContext, IContext

  27: {

  28:  

  29:    public DbSet<TEntity> CreateSet<TEntity>() where TEntity : class

  30:    {

  31:        throw new NotImplementedException();

  32:    }

  33:  

  34:    public void Commit()

  35:    {

  36:        throw new NotImplementedException();

  37:    }

  38:  

  39:    public void RollBack()

  40:    {

  41:        throw new NotImplementedException();

  42:    }

  43: }

Mirad lo que puedo hacer, ooooo!!!

   1: public class Test

   2: {

   3:     public Test()

   4:     {

   5:         using (Contexto ct = new Contexto())

   6:         {

   7:             var idCliente =10;

   8:             var repositorio = new RepositoryCliente(ct);

   9:             //Devolver un cliente

  10:             var cliente = repositorio.Get(idCliente, c => c);

  11:             //Devolver partes de un cliente

  12:             var formapago = repositorio.Get(idCliente, c => new { Id = c.FormaPago.Id, Nombre = c.FormaPago.Nombre });

  13:             

  14:         }

  15:     }

  16: }

Pero lo que más me gusta es esto.

Dibujo

Pedro la verdad que eres un sacrílego, no se cuantos principios  has roto y cuantos antipatrones has implementado, además un método que devuelve un Tipo Anónimo.

Yo me contesto. Si lo que tu me digas, pero yo necesito el Id y el Nombre de la Forma de Pago no doscientos campos que tiene el Cliente. Anda derrochador,malgastoso no vas a tener ni un duro cuando seas mayor:).

Conclusiones.

Porque no nos acostumbramos a leer exclusivamente lo que necesitamos y nos dejamos de películas, creo que la vida nos irá mejor. Una última reflexión, ¿me habré cargado AutoMapper?. Otro malgastoso, o estoy en el camino:).

Var (II).Los hermanos de Simba

Este post viene como consecuencia de los comentarios del gran @eiximenis, en este otro var en c# si, o var no. Lo que ha hecho Eduard es elevar con la segunda respuesta la entrada al destino de los elegidos:).

Referente al titulo “Los hermanos de Simba” es porque la fiera se va a comer al gatito.

La primera de las respuestas, he de reconocer que estuve pensando en escribirla en el primero de los post, pero eso de la vida que te hace perezoso y en un momento decides cortar.

Eduard nos dice lo siguiente.

Efectivamente, como bien dices en var el tipo del lvalue es siempre igual al del rvalue (eso es var precisamente). Pero, en según que ocasiones, eso no nos sirve… Un ejemplo rápido…

myListbox.Items.Add(new Foo());

foreach (var fooItem in myListbox.Items) { … }

En este caso, al usar var, fooItem es un Object, pero si yo sé que en la lista hay solo Foo, probablemente querré que fooItem sea de tipo Foo. Este es solo un ejemplo. A eso me refería yo 😉

Por que ocurre esto? Porque en el ejemplo Eduard está utilizando un ObjectCollection, claro a alguien le pareció demasiado tedioso con la aparición de generic reescribir Windows Form y demás y lo que se hizo fue dejar la cosa como estaba e implementar IEnumerable<T>, todos sabemos que para utilizar el magnifico foreach alguien debe de implementar en sus clases como mínimo IEnumerable y digo como mínimo, puesto que lo lógico es utilizar IEnumerable<T>.

Vamos con un ejemplo, partimos de la siguiente clase.

   1: public class Foo

   2: {  

   3:    

   4: }

Si yo escribo el siguiente conjunto de instrucciones

   1: var foo = new Foo();

   2: foreach (var item in foo)

   3: {

   4:  

   5: }

Recibo un error de compilación donde me dice lo siguiente.

La instrucción foreach no puede funcionar en variables de tipo ‘Namespace.Foo’ porque ‘Namespace.Foo’ no contiene ninguna definición pública para ‘GetEnumerator’.

Sí Implementamos IEnumerable en “Foo”.

   1: public class Foo:System.Collections.IEnumerable

   2: {

   3:  

   4:     public System.Collections.IEnumerator GetEnumerator()

   5:     {

   6:         throw new NotImplementedException();

   7:     }

   8: }

A partir de este momento yo puedo ejecutar foreach in “Foo”.

Pero claro, con esto no contestamos a Eduard, para ello nos debemos fijar en el valor devuelto por GetEnumerator un IEnumerator cuya definición es la siguiente.

   1: [ComVisible(true), Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]

   2: public interface IEnumerator

   3: {

   4:     bool MoveNext();

   5:     object Current { get; }

   6:     void Reset();

   7: }

   8:  

Si nos fijamos Current es object, por eso es por lo que a “var” se le asigna un “object”, con lo cual “var” si está haciendo lo que dice hacer.

Claro porque “var” si funciona con List<T>,etc,etc, pues sencillo porque estos han subido un nivel y han implementado IEnumerable<T> y por tanto IEnumerator<T> donde la  propiedad Current devuelve T.

   1: public interface IEnumerator<T> : IDisposable, IEnumerator

   2: {

   3:     // Properties

   4:     T Current { get; }

   5: }

Pero como se que me va a decir que porque yo puede hacer lo siguiente.

   1: private void Metodo()

   2: {

   3:     var Lista = new System.Collections.ArrayList();

   4:     Lista.Add(new Foo());

   5:     foreach (Foo item in Lista)

   6:     {

   7:  

   8:     }

   9: }

Le vamos a contestar, con un simple “una cosa es lo que tus ojos ven y otra bien distinta lo que hay”.

Un poquito de IL:).

   1: .method private hidebysig instance void Metodo() cil managed

   2: {

   3:     .maxstack 2

   4:     .locals init (

   5:         [0] class [mscorlib]System.Collections.ArrayList Lista,

   6:         [1] class WindowsFormsApplication24.Foo item,

   7:         [2] class [mscorlib]System.Collections.IEnumerator CS$5$0000,

   8:         [3] bool CS$4$0001,

   9:         [4] class [mscorlib]System.IDisposable CS$0$0002)

  10:     L_0000: nop 

  11:     L_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()

  12:     L_0006: stloc.0 

  13:     L_0007: ldloc.0 

  14:     L_0008: newobj instance void WindowsFormsApplication24.Foo::.ctor()

  15:     L_000d: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)

  16:     L_0012: pop 

  17:     L_0013: nop 

  18:     L_0014: ldloc.0 

  19:     L_0015: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.ArrayList::GetEnumerator()

  20:     L_001a: stloc.2 

  21:     L_001b: br.s L_002b

  22:     L_001d: ldloc.2 

  23:     L_001e: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()

  24:     L_0023: castclass WindowsFormsApplication24.Foo

  25:     L_0028: stloc.1 

  26:     L_0029: nop 

  27:     L_002a: nop 

  28:     L_002b: ldloc.2 

  29:     L_002c: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()

  30:     L_0031: stloc.3 

  31:     L_0032: ldloc.3 

  32:     L_0033: brtrue.s L_001d

  33:     L_0035: leave.s L_0051

  34:     L_0037: ldloc.2 

  35:     L_0038: isinst [mscorlib]System.IDisposable

  36:     L_003d: stloc.s CS$0$0002

  37:     L_003f: ldloc.s CS$0$0002

  38:     L_0041: ldnull 

  39:     L_0042: ceq 

  40:     L_0044: stloc.3 

  41:     L_0045: ldloc.3 

  42:     L_0046: brtrue.s L_0050

  43:     L_0048: ldloc.s CS$0$0002

  44:     L_004a: callvirt instance void [mscorlib]System.IDisposable::Dispose()

  45:     L_004f: nop 

  46:     L_0050: endfinally 

  47:     L_0051: nop 

  48:     L_0052: ret 

  49:     .try L_001b to L_0037 finally handler L_0037 to L_0051

  50: }

y más concretamente nos vamos a centrar en estás dos instrucciones

   1: L_001e: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()

   2: L_0023: castclass WindowsFormsApplication24.Foo

Hombre un OpCodes.Castclass. Lo más bonito de este link no es otra cosa que la siguiente frase.

“Intenta convertir un objeto pasado por referencia en la clase especificada”

Efectivamente “intenta”, con lo cual si no puede, sorpresa y nos llevaremos como premio, un magnifico “InvalidCastException” y para ello simplemente creamos una clase Foo1 y la agregamos al ArrayList.

   1: private void Metodo()

   2: {

   3:  var Lista = new System.Collections.ArrayList();

   4:  Lista.Add(new Foo());

   5:  Lista.Add(new Foo1());

   6:  foreach (Foo item in Lista)

   7:  {

   8:  

   9:  }

  10: }

Lo que es evidente, que var funciona, puesto que es imposible saber que es lo que ArrayList tiene. Solo sabemos que tiene object y por tanto “var” es “object”.

Pero se te olvido una cosa OfType<T>() y entonces “var” si que funciona perfectamente, aunque que quede claro que no aconsejo el uso de esta instrucción en este caso, puesto que nos comemos un elemento. Lo que si aconsejo es que nos olvidemos para siempre si puede ser de las colecciones no genericas, aunque algunas veces es imposible y más cuando se trata de collecction ligadas a WindowsForm,WPF,Silverlight, que bastante mal se llevan con el uso de Generic.

En definitiva para que “var” funcione correctamente en este caso basta con escribir lo siguiente.

   1: private void Metodo()

   2: {

   3:     var Lista = new System.Collections.ArrayList();

   4:     Lista.Add(new Foo());

   5:     Lista.Add(new Foo1());

   6:     foreach (var item in Lista.OfType<Foo>())

   7:     {

   8:  

   9:     }

  10: }

Aunque como dije anteriormente el segundo elemento nos lo comemos, de esta forma veo que yo si utilizaría “var” siempre en un foreach.

Cuando me refería a no abusar,  me refería, aunque se puede, a utilizar este tipo de cosas.

   1: var i = ((Func<int, int, int>)((x, y) => x + y))(10,10);

Esto me recuerda a un antiguo compañero que cuando sumaba enteros escribía “var z = 0x3e8 + 0x3e8;” que si hombre que sí que z = 2000 ó z = 1000+ 1000;

Aclarado el primer comentario, vamos con el segundo que ese si que está lleno de mala leche:).

La pregunta es… Suponiendo que lo anterior compilase, esa otra línea debería hacerlo?

var r = (x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17 => x1+x17)(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);

Repito: si la sentencia anterior compilase, esa debería compilar también? Sí? No? Tic, tac…

PD: Si, admito que si alguien crea una lambda con 17 parámetros es para darle una colleja 😛

La respuesta es No y os explico, para ello nos debemos trasladar a la primera aparición de Func y Action en el Framework 3.5. El número maximo de parametros permitidos eran 4.

Dibujo

Si avanzamos en el tiempo y analizamos esto mismo a partir del Framework 4.0 nos encontramos con que los parametros permitidos son 16, fijaos en la maldad de poner 17:).

Dibujo

tic,tac…. Pero no conformándonos con esto vamos a demostrarle a Eduard que si  compilo.

Alguien me impide a mí definir un Func y un Action con 17 parámetros o con 50, pues no otra cosa es que directamente te pueden llamar “ñapas”:).

   1: namespace System

   2: {

   3:     public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16,in T17, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16,T17 arg17); 

   4:  

   5: }

Y ahora vamos a hacer que compile utilizando “var”.

   1: var i = ((Func<int, int, int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int>)

   2:                ((x1, x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17) => 

   3:                  x1+x2+x1+x4+x5+x6+x7+x8+x9+x10+x11+x12+x13+x14+x15+x16+x17))

   4:                (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);

   5: Console.Write(i);

El resultado obtenido que es pues sencillo 151, pero claro no debéis de utilizar esta técnica para sumar una secuencia de números correlativa, mas vale que  veáis este video.

http://www.youtube.com/watch?feature=player_embedded&list=PLB33C2EAFBCB22655&v=9gv2YyRvdB0

Tic,Tac……

Saludos,

var en c# si, o var no

Este es de esos post donde uno piensa exactamente igual que cuando deshoja una margarita. Me quiere no me quiere. Mi opinión antes de seguir es que la quiero:).

Todo esto surge a raíz de una conversación en twitter que podéis seguir aquí y que lógicamente expuso diferentes opiniones que al final es en lo que consiste, Yo opino, tu opinas.

¿Quien tiene la razón? todos:).

Un poco de puesta en escena

https://twitter.com/#!/_PedroHurtado/status/202057547094564864, claro yo haciendo caso omiso a los consejos de mi padre “Pedro Dios te dio dos orejas para escuchar el doble de lo que hablas”. No se me ocurre otra cosa que lanzar esto:).

https://twitter.com/#!/_PedroHurtado/status/202058984570621953 y después no conforme con esto un poco más de fuerza bruta.

https://twitter.com/#!/_PedroHurtado/status/202060219935756288

Con lo cual surge todo esto.

https://twitter.com/#!/_PedroHurtado/status/202061813746110464 y más. Que no es necesario hacerse pesado y vamos al grano.

Que es var?

De las pocas cosas que da gusto leer en el MSND y uno se entera. Es la definición de Variables locales con asignación implícita de tipos (Guía de programación de C#).

Pero si nos centramos en esto vemos cosas que deberían tener algún que otro comentario.

“A las variables locales se les puede asignar un «tipo» deducido var en lugar de un tipo explícito. La palabra clave var indica al compilador que deduzca el tipo de la variable a partir de la expresión que se encuentra en el lado derecho de la instrucción de inicialización”

Efectivamente Eduard(@eiximenis), discrepo totalmente en tu afirmación “cuando el tipo del lvalue es distinto al tipo del rvalue… ;)” no creo que lvalue entendido como la parte izquierda sea distinto jamás al rvalue es decir el lvalue es deducido o mejor dicho inferido a partir del rvalue, con lo cual todo es valido para “var” y lo vamos a ver:).

@Jonathan_JFR, te voy a explicar porque los tipos anónimos o lambda expresion no se pueden inferir, para ello te recomiendo esta lectura Why can’t an anonymous method be assigned to var?. En la cual el gran Eric Lippert metió la pata hasta donde se puede meter:), me quedo con la respuesta de Mehrdad.

“@Eric: Good answer, but it’s slightly misleading to illustrate this as something that’s not possible, as this actually works completely fine in D. It’s just that you guys didn’t choose to give delegate literals their own type, and instead made them depend on their contexts… so IMHO the answer should be «because that’s how we made it» more than anything else. :)”

Pues si Eriq es confuso y te voy a poner un ejemplo sencillo.

var i = 123;

Esto que es?

Un int,uint,short,ushort,long,ulong,sbyte,byte

¿Por qué se infiere un int?

Creo que “porque así se decidió”.

Con lo cual tu para inferir un «tipo integrado” o un ValueType te tienes que ir a la siguiente tabla.

Tabla de valores predeterminados (Referencia de C#).

En resumen si yo quiero hacer que i sea del tipo Decimal tengo que hacer esto.

var i=123M; o bien var i = 123m; es decir hacer uso de los Literales y más concretamente de los sufijos de estos o bien en el caso de short que no lo tiene hacer uso de lo siguiente.

var i=(short)0;

A partir de este momento es fácil deducir como una Lambda Expresion o bien un Método Anónimo lo puedo poner a la derecha de “var”.

   1: var i = delegate(int y) //Error No se puede asignar metodo anonimo a una variable local tipificada implicitamente

   2: {

   3:    return y * 2;

   4: };

   5: var i = ((Func<int,int>)delegate(int y) //Ok

   6: {

   7:    return y * 2;

   8: });

Ahora vamos con las Lambda Expresion, estás pueden devolver o un Func,etc,etc o bien o una Expresión es decir esto sería un Func.

   1: Func<int, int, int> b = (x,y)=>x*y;

o eso mismo podría ser

   1: Expression<Func<int, int, int>> b = (x, y) => x * y;

Alguien me impide a mi hacer esto.

   1: var i = (int x, int y) => x * y;

Si el compilador, pero que ocurre si hago lo siguiente, pues que todo funciona.

   1: var i = (Func<int,int,int>)((x,y)=>x+y);

   2: var resultado = i(10, 10);

   3: Console.WriteLine(i.GetType());

   4: Console.WriteLine(resultado.GetType());

   5: Console.WriteLine(resultado);

Os imagináis el resultado, pues os lo muestro.

System.Func`3[System.Int32,System.Int32,System.Int32]

System.Int32

20

Otra cosa, puede hacer esto?.

var i = null, pues no y para ello lo mejor que podemos es revisar lo siguiente. Implicitly Typed Local Variables, concretamente el apartado de “restrictions”.

Pues sí puedo hacer y muchas cosas más.

   1: var nullint32 =(int?)0;

   2: var nulo = (Clase)null;

   3: var xByte = (byte)0;

   4: var Xdecimal= 0M;

   5: var XLong = 0L;

   6: var XDouble = 0D;

   7: var XUint = 0U;

   8: var XShort = 0;

   9: var xFloat = 0F;

  10: var XChar = '1';

  11: var XEnum = (aaa)1;

  12: var xShort = (short)32767;

Y de esta forma todas las que se os ocurran:).

Conclusiones.

1. Que como todo tiene su razón de ser, que se puede utilizar y ahorrar trabajo es evidente.

2. Que si  abusamos puede llegar a ser malo, también.

3. Yo lo utilizo siempre en linq, tipos anonimos,al crear un nuevo objeto, en using,devoluciones de metodos y foreach y hasta el momento no he tenido ningún problema.

4. Es el Dim de Vb. Nooooooooooooooo.

5. Es un variant de vb o bien un object de c#. Nooooooooo, si revisamos el IL vemos que exactamente tanto una como la otra sentencia genera lo mismo.

int i = 10;

var i=10;

6. Es confuso Noooooooooo, para mi confuso es no poner nombres claros a las variables, eso si que es confuso.

El scroll infinito.

Hola, os acordáis de Pepe, si hombre el usuario que nos ayudo a crear el patrón “Engañabobos”.  Seguro que a alguno y es normal le puede sonar a risa, por eso lo lógico, es que leáis antes este post .

Después de pensar que todo estaba solucionado, suena el teléfono y como no, es otra vez “Pepe”. Su frasecita “esto sigue igual de lento”.

Nos ponemos a trabajar,pensamos en voz alta y decimos :

1. Si estamos paginando.

2. Hemos hecho un análisis de las consultas y todas van bien.

Que puede pasar? Minutos después nos dimos cuenta que si que estábamos haciendo todo eso , pero….

Se ejecutaba un “SELECT COUNT()” en cada Round-Trip, para mostrar el número de paginas al usuario.

Efectivamente hemos localizado el problema, pero como lo solucionamos, pues sencillo y por eso el título.

Alguien utiliza twitter, a que sí, pues vamos a hacerlo para MVC.

1. Definimos una clase sencilla llamada Datos. Hoy no tenemos entidades ni EF, ni nada de eso.

   1: using System;

   2: using System.Collections.Generic;

   3: using System.Linq;

   4: using System.Web;

   5:  

   6: namespace MvcApplication17.Models

   7: {

   8:     public class Datos

   9:     {

  10:         public int Id { get; set; }

  11:         public string Nombre { get; set; }

  12:     }

  13: }

2. En nuestro controlador vamos a escribir lo siguiente en el método Index.

   1: public ActionResult Index(int? Pagina)

   2: {

   3:     ViewBag.Message = "Welcome to ASP.NET MVC!";

   4:  

   5:     List<Datos> datos = new List<Datos>();

   6:  

   7:     for (int i = 0; i < 500; i++)

   8:     {

   9:         int id = i+1;

  10:         datos.Add(new Datos() { Id = id, Nombre = string.Format("Nombre {0}", id) });

  11:     }

  12:  

  13:     var Skip = Pagina ?? 0;

  14:     var Take = 50;

  15:     var model = datos.Skip(Skip * Take).Take(Take);

  16:  

  17:     if (!Request.IsAjaxRequest())

  18:     {

  19:         return View(model);

  20:     }

  21:     else

  22:     {

  23:         return Json(model, JsonRequestBehavior.AllowGet);                                     

  24:     }

  25: }

Fijaos en un detalle “Request.IsAjaxRequest()”, con esto lo que hago es controlar si me están haciendo peticiones vía Ajax.

3. Nos queda la vista y un poco de algunas cosas. Siguiendo este magnífico post de @jmaguilar y viendo que podemos utilizar MVVM,uno de mis favoritos, nos ponemos manos a la obra:).

Para ello voy a utilizar dos referencias que podéis encontrar en la pagina oficial de knockout.

The "template" binding

The "attr" binding

Es decir nuestra vista va a quedar de la siguiente forma.

   1: @using MvcApplication17

   2: @model IEnumerable<MvcApplication17.Models.Datos>

   3:            

   4: @{

   5:     ViewBag.Title = "Home Page";    

   6: }

   7: <script src="@Url.Content("~/Scripts/knockout.js")" type="text/javascript"></script>
   1:  

   2: <h2>@ViewBag.Message</h2>

   3:  

   4: <p>

   5:     @Html.ActionLink("Create New", "Create")

   6: </p>

   7:  

   8: @*Tabla*@

   9: <table data-bind="template: { name: 'data-template', foreach: items }">

  10: <thead>

  11:     <tr>        

  12:         <th>Nombre</th>

  13:         <th></th>

  14:     </tr>

  15: </thead>

  16: </table> 

  17:  

  18: @*Template*@

  19: <script type="text/html" id="data-template">

  20:     <tr>    

  21:     <td data-bind="text: Nombre"></td>    

  22:     <td>

  23:         <a data-bind="attr: { href: 'Home/Edit/' + Id}">Edit</a>|

  24:         <a data-bind="attr: { href: 'Home/Details/' + Id}">Details</a>|

  25:         <a data-bind="attr: { href: 'Home/Delete/' + Id}">Delete</a>

  26:      </td>

  27:     </tr>

</script>

Claro esto no hace absolutamente nada, para ello, tenemos que utilizar javascript y dar vida a esta paginación.

   1: <script type="text/javascript">

   2: var Home_Index = {

   3:     items:ko.observableArray(@Html.Raw(@Json.Encode(Model))),

   4:     pagina:0,

   5:     endData:false,

   6:     redord:50,

   7:     scroll:function(){

   8:         if(($(window).scrollTop() == $(document).height() - $(window).height()) && !Home_Index.endData){

   9:             Home_Index.pagina++;

  10:             $.getJSON('Home/Index',{pagina:Home_Index.pagina},Home_Index.nextPage)

  11:         }

  12:     },

  13:     nextPage :function(data){

  14:         if (data.length>0){

  15:             $.each(data, function(i, item){

  16:                 Home_Index.items.push(item);

  17:             });

  18:         }      

  19:  

  20:         if (data.length < Home_Index.record){

  21:            Home_Index.endData=true;

  22:             Home_Index.paginga--;

  23:      

  24:         }

  25:     }              

  26: };

  27: ko.applyBindings(Home_Index);

  28: $(window).scroll(Home_Index.scroll);

  29: </script>

Y de repente nos encontramos con que “Pepe” está contento podemos paginar sin hacer un Count().

En definitiva nos tenemos que centrar en lo siguiente.

items:ko.observableArray(@Html.Raw(@Json.Encode(Model))),

Con esto evitamos que en la primera llamada tengamos que hacer una nueva llamada via ajax, cosa que he visto en muchas ocasiones. Cargar la pagina y después uno de los plugin hace una llamada para refrescar los datos.

El resto poca explicación tiene para los más puestos en javascript  excepto esta línea de la que podéis ampliar información Observables .

ko.applyBindings(Home_Index);

Claro alguno dirá, pero estar compiando esto en cada vista, como que no, pues os voy a dar una idea, podéis utilizar un método extensor y extender el objeto HmtlHelper, os paso la firma del método y quien quiera que se ponga manos a la obra:)

   1: public static class MisHelper

   2: {

   3:     public static MvcHtmlString InfiniteScroll(this System.Web.Mvc.HtmlHelper Helper,string Controller, string Action,int Record,object Model)

   4:     {

   5:         string Type = string.Format("{0}_{1}",Controller,Action);

   6:         StringBuilder sb = new StringBuilder();          

   7:         

   8:         //El resto es trabajo vuestro:)

   9:          

  10:         TagBuilder script = new TagBuilder("script");

  11:         script.Attributes.Add("Type", "text/javascript");

  12:         script.InnerHtml = sb.ToString();

  13:  

  14:       

  15:  

  16:         return new MvcHtmlString(script.ToString(TagRenderMode.Normal));

  17:     }

  18: }

Si hacemos esto conseguiremos en nuestra vista no tener esa cantidad de javascript y ejecutar esto vía razor.

@Html.InfiniteScroll("Home", "Index", 50, Model);

Como todos no son virtudes y existe algún que otro problema y sobre todo con Javascript y el formateo de fechas y números que lo odio:). Os voy a contar otra forma que se me ha ocurrido.

Separar mi vista en dos y las filas de la tabla generarlas en una vista parcial.

1. Controlador.

   1: public ActionResult Index(int? Pagina)

   2: {

   3:    ViewBag.Message = "Welcome to ASP.NET MVC!";

   4:  

   5:    List<Datos> datos = new List<Datos>();

   6:  

   7:    for (int i = 0; i < 500; i++)

   8:    {

   9:        int id = i+1;

  10:        datos.Add(new Datos() { Id = id, Nombre = string.Format("Nombre {0}", id) });

  11:    }

  12:  

  13:    var Skip = Pagina ?? 0;

  14:    var Take = 50;

  15:    var model = datos.Skip(Skip * Take).Take(Take);

  16:  

  17:    if (!Request.IsAjaxRequest())

  18:    {

  19:        return View(model);

  20:    }

  21:    else

  22:    {

  23:        return PartialView("_TableIndex", model);

  24:        //return Json(model, JsonRequestBehavior.AllowGet);                                     

  25:    }

  26: }

Si os fijáis la diferencia es sencilla en vez de devolver Json lo que hago es devolver un PartialViewResult.

2. Nuestra vista quedaría de la siguiente forma.

   1: @using MvcApplication17

   2: @model IEnumerable<MvcApplication17.Models.Datos>

   3:            

   4: @{

   5:     ViewBag.Title = "Home Page";    

   6: }

   7:  

   8: <h2>@ViewBag.Message</h2>

   9:  

  10: <p>

  11:     @Html.ActionLink("Create New", "Create")

  12: </p>

  13:  

  14: <table id = "Grid">

  15:     <tr>

  16:         <th>

  17:             Nombre

  18:         </th>

  19:         <th></th>

  20:     </tr>

  21:     @Html.Partial("_TableIndex",Model)

  22: </table>

  23: <script type="text/javascript">
   1:  

   2:     var Home_Index = {

   3:         pagina: 0,

   4:         endData: false,

   5:         redord: 50,

   6:         scroll: function () {

   7:             if (($(window).scrollTop() == $(document).height() - $(window).height()) && !Home_Index.endData) {

   8:                 Home_Index.pagina++;                

   9:                 $.get('Home/Index', { pagina: Home_Index.pagina }, Home_Index.nextPage);

  10:             }

  11:         },

  12:         nextPage: function (data) {           

  13:             data = data.replace(/^s*|s*$/g, "");

  14:             alert($(data).size())

  15:             if ($(data).length > 0) {

  16:             $('#Grid tr:last').after(data);

  17:             }

  18:             else {

  19:             Home_Index.pagina--;

  20:             Home_Index.endData = true;

  21:             }

  22:         }

  23:     };

  24: $(window).scroll(Home_Index.scroll);

</script>

3. Nuestra vista parcial.

 

   1: @model IEnumerable<MvcApplication17.Models.Datos>

   2: @foreach (var item in Model) {

   3:     <tr>

   4:         <td>

   5:             @Html.DisplayFor(modelItem => item.Nombre)

   6:         </td>

   7:         <td>

   8:             @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |

   9:             @Html.ActionLink("Details", "Details", new { id=item.Id }) |

  10:             @Html.ActionLink("Delete", "Delete", new { id=item.Id })

  11:         </td>

  12:     </tr>

  13: }

 

Analicemos pues las ventajas y desventajas de utilizar esta última, tenemos más control como se puede ver gracias a Razor y el trabajo en el servidor, por contra al devolver html la diferencia en bytes entre utilizar la primera y la segunda forma  es notable 12 Kb frente a 1.5 Kb devolviendo Json en cada petición, es decir bastante diferencia.

Conclusiones.

Poco tiene esto que decir, mas que educar a nuestros usuarios para adaptarse a nuevas formas de ver la información y que pequeños detalles como este, hacen que una aplicación corra o se arrastre:).

Con esto cerramos los proxis dinámicos de EF

En mi anterior post y con bastante ánimo de critica intente explicar mi desacuerdo con ciertas cosas que pasan sin nuestro control. En este lo que intento es que todos conozcáis que es lo que pasa con algunas recomendaciones “Si trabajas con EF declara tus propiedades como virtual que es mejor” .

Mejor ¿Por qué?. Vamos a verlo:).

Si pensamos detenidamente cuando yo declaro algo con el modificador de acceso virtual es porque lo dejo preparado para que otra persona sea capaz de reemplazarlo con override. Es así no?.

Para poneros un poco en antecedentes os recomiendo estos dos post que os pueden ayudar a aclarar ciertas dudas.

Seguro que más de uno lo ha leído, pues Codefirst funciona igual y sino de donde la magia.

Pero me quedo con esta frase “Proxies are a form of dependency injection where additional functionality is injected into the entity”. Para mi no es Inyección de dependencias yo creo que mas que eso es una invasión:).

Otra cosa que me dio bastantes pistas fue esto

“The EF generates proxy types on the fly using the AssemblyBuilder and TypeBuilder in the .NET framework. All the code to perform lazy loading and change tracking is added to the dynamically generated types using the Reflection.Emit APIs”

Mi gran amigo Reflection.Emit desconocido pero potente para invadir. Bueno llegados a este punto, es darle un poco a la imaginación y a las malas artes para descubrir quien hace todo eso. Tras dar vueltas al código fuente con Reflector me encuentro con una clase internal. Como no!!!. Señores public y si puede ser  OpenSource que esto hará que EF crezca.

Sabéis el nombre pues os lo digo

Clase :“EntityProxyFactory” 

Namespace:“System.Data.Objects.Internal”

Dll: “System.Data.Entity.dll”.

Si esa que esta instalada en la GAC y que por mucho que con Nuget actualicemos la versión de EF nunca cambia.

Os acordáis de mi anterior post ese modelo malicioso de Facturas y Clientes,  bueno ahora voy a hacer con el otra cosa y es ver que genera EF por nosotros.

Para ello voy a utilizar reflection y acceder a ciertos campos privados de esa clase y modificarlos para poder guardar en disco la dll generada.

   1: BindingFlags Flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

   2: using (ModelFacturas db = new ModelFacturas())

   3: {

   4:    //Obtenemos el ensamblado System.Data.Entity.Dll

   5:    Assembly a = typeof(System.Data.Objects.ObjectContext).Assembly;

   6:    

   7:    //Obtenemos el tipo EntityProxiFactory

   8:    var type = (from item in a.GetTypes()

   9:                where item.Name == "EntityProxyFactory"

  10:                select item).FirstOrDefault();

  11:  

  12:    //Modificamos el campo privado s_ProxyAssemblyBuilderAccess para

  13:    //permitir que el ensamblado dinamico se pueda guardar

  14:    //por defecto AssemblyBuilderAccess está marcado como Run

  15:    //Es decir se puede ejecutar pero no se puede Guardar

  16:    var field = type.GetField("s_ProxyAssemblyBuilderAccess", Flags);

  17:    

  18:    object o = Activator.CreateInstance(type);

  19:    field.SetValue(o, AssemblyBuilderAccess.RunAndSave);

  20:  

  21:    //provocamos que EF genere el proxi dinamico

  22:  

  23:    var cliente = db.Clientes.AsEnumerable().FirstOrDefault();

  24:    var facturas = db.Facturas.AsEnumerable().FirstOrDefault();             

  25:    

  26:    //Accedemos al ensamblado dinamico y lo guardamos en disco

  27:    var field2 = type.GetField("s_ModuleBuilders", Flags);

  28:  

  29:    Dictionary<Assembly, ModuleBuilder> dic = field2.GetValue(o) as Dictionary<Assembly, ModuleBuilder>;

  30:    if (dic.Any())

  31:    {

  32:        AssemblyBuilder asm = dic.First().Value.Assembly as AssemblyBuilder;

  33:        asm.Save("tequieroconocer.dll");

  34:    }   

  35: }

Pues a partir de este momento ya tenemos en nuestro directorio de ejecución.  Una dll llamada “tequieroconocer.dll”. El siguiente paso es sencillo la abrimos con cualquier herramienta como Reflector y a disfrutar y conocer:).

Dibujo

 

Fijaos en la magia, nuestras clases originales han sido alteradas e implementan dos interfaces

El resto de cosas os las dejo para que investiguéis, vosotros y de esa forma conocer a fondo este Framework, que tiene sus cosas buenas y otras que no son tan buenas.

Conclusiones.

El conocimiento no debe de tener limites , por lo tanto tiene que ser público y es por esto el motivo de este post.

Sobre todo os tenéis que acordar de dos parámetros importantes cuando utilicéis EF.

Ya conocéis un poquito más de ellos.