Codepoint

by Trentia Consulting

Novedades de Entity Framework 5.0

Entre las nuevas funcionalidades que encontramos en la nueva versión, todavía en Release Candidate, de Entity Framework, podríamos destacar:

  1. Nuevos tipos de datos.
    • Tipos enumerados (Enum)
    • Tipos de datos espaciales, expuestos mediante los tipos DBGeography y DbGeometry.
  2. Posibilidad de trabajar con funciones que devuelven datos tabulares. El resultado es similar a la llamada a un procedimiento almacenado, con la diferencia de que podemos utilizar estas funciones en consultas LINQ
  3. Todas las consultas LINQ se compilan y cachean de forma automática. Con ello se obtiene un mejor rendimiento en llamadas recurrentes a las consultas
  4. Soporte a múltiples diagramas para un mismo modelo de datos. Se podrán visualizar partes del modelo completo en diagramas más pequeños, con lo que se mejora la lectura y exploración del modelo
  5. Mejoras generales en el rendimiento de EF respecto a versiones anteriores
  6. Posibilidad de utilizar procedimientos almacenados que devuelven múltiples conjuntos de resultados. Cada conjunto de resultados del procedimiento será mapeando un tipo complejo propio

Está previsto que EF 5.0 sea liberado a través de paquetes de NuGet, siguiendo un calendario distinto al de .NET Framework 5.0, lo cual no sabemos si es mejor o peor. Lo que está claro es que cada versión de EF nos trae importantes y esperadas novedades, tanto funcionales como de rendimiento y la versión 5.0 no es una excepción.

Solucionar problema con la intercalación desde Linq

En caso de necesitar realitzar búsquedas contra el motor de base de datos sin tener en consideración mayúsculas/minusculas, acentos y otros símbolos de puntuación, desde SQL Server es necesario que la base de datos use una intercalación *_CI_AI

Pero aunque la base de datos esté bien configurada para que las consultas sean no sensitivas a este tipo de carácteres, si se realiza la consulta desde nuestra aplicación la consulta no será efectiva puesto que desde linq no se explota la facilidad que nos ofrece la base de datos.

Para solucionar esto hay un método que es el que muestro en el siguiente código:

string ntext = new string("TEXTO_A_BUSCAR".Normalize(NormalizationForm.FormD).Where(c => c < 128).ToArray());
Lista = Lista.Where(x => (UTF8Encoding.UTF8.GetString(UTF8Encoding.GetEncoding("ISO-8859-8").GetBytes(x.CAMPO_BD)).IndexOf(ntext, StringComparison.InvariantCultureIgnoreCase) > -1)).ToList();

En la primera instrucción normalizamos el texto a localizar en la base de datos, y en la segunda se realiza la búsqueda en sí misma sobre el campo de la base de datos con el cual deseamos hacer el filtro.

Espero que os sirva de ayuda.

Consejos para mejorar el rendimiento de tu Entity Framework (VI)

Cargar objetos con el EF.

Desde el framework puedes cargar relaciones usando  include. Por cada uno, el framework añadirá un join que puede originar consultas complejas, y que sean devueltas grandes cargas de datos. A este tipo de cargas se les llama "Eager loading".

Sin embargo, esto puede ser evitado usando el método Load para hacer "lazy or explicit loading”, que abre una conexión a base de datos para recuperar la información necesaria.
Así nos aseguramos de que la consulta  sólo ejecutará una petición a un objeto relacionado mediante una petición explícita. 

Por ejemplo:

// Get a specified customer by contact ID.
Contact customer = context.Contact.Where("it.ContactID = @customerId", 
                   new ObjectParameter("customerId", customerId)).First();
// Load the orders for the customer
if (!customer.SalesOrderHeader.IsLoaded)
{
    customer.SalesOrderHeader.Load();
}

El código completo  de este ejemplo se  encuenta en este artículo del msdn de Microsoft.

Filtra los datos.

Cuando se usa este tipo de carga (con Load o con LoadWith) se reciben todos los datos asociados con la clave primaria, pero la mayoría de los casos se deben aplicar filtros adicionales. Para ello se usa el método  DataLoadOptions.AssociateWith, que toma el criterio al cargar los datos como parámetro y aplica la consulta.  

using (DataContext context = new DataContext())
{
  DataLoadOptions options = new DataLoadOptions();
  options.AssociateWith(cat=> cat.Products.Where(prod => !prod.Discontinued));
  context.LoadOptions = options;
}

Via:  http://msdn.microsoft.com/en-us/library/system.data.linq.dataloadoptions.associatewith.aspx

Consejos para mejorar el rendimiento de tu Entity Framework (V)

Pequeños ficheros EDMX.

El DataContext representa una unidad de trabajo, no toda la base de datos.

El tamaño del esquema .xml es proporcional al número de tablas de la base de datos desde el que se genera, y como el tamaño del archivo aumenta, también aumentará el tiempo que tarda en crear el modelo en memoria para este metadata. Además el diseñador del Visual Studio también comienza a navegar en la peor eficiencia cuando el número de entidades es muy alta.
Si tienes un modelo muy interconectado puedes tener problemas de rendimiento, y hay que pensar en la posibilidad de dividirlo en varios archivos edmx, cuando tienes del orden de 100 entidades.

La desventaja de tener varios pequeños modelos de datos es que tendrás que mantener varios .edmx sincronizados cuando haces cambios en la base de datos.

Consejos para mejorar el rendimiento de tu Entity Framework (IV)

Usar consultas pre-compiladas.

La creación de consultas consume sobre un 10% de la ejecución de ésta. Algunas partes se cachean y las siguientes son más rápidas, pero otras partes no, así que se reconstruye cada vez que la consulta se ejecuta (a no ser que se use EntitySql).

Por eso cuando una aplicación ejecuta muchas veces consultas que tienen una estructura similar en EF se mejora el  rendimiento si se compila la consulta una vez y se ejecuta varias veces con parámetros diferentes que son especificados en tiempo de ejecución. 
Para ello se usa el método CompiledQuery.Compile, el cual usa un delegado Func genérico. Almacenando y usando de este modo también se reduce el coste de hacer una llamada virtual, cada vez que accedes a la colección, que de hecho se reduce a una llamada. Además, ésta será compilada sólo la primera vez que la consulta se ejecute. Pero, si usas CompiledQuery , asegúrate de que se llama a la consulta más de una vez, ya que  la primera vez que se lanza, tarda el doble de tiempo que una consulta simple sin cachear.

Éste es el ejemplo  de Microsoft  para la creación de una consulta compilada:

static readonly Func> s_compiledQuery2 = 
    CompiledQuery.Compile>(
            (ctx, total) => from order in ctx.SalesOrderHeader
                            where order.TotalDue >= total
                            select order);

Para más información, o ver el código completo se puede consultar el artículo completo de Microsoft.

Via: http://msdn.microsoft.com/en-us/library/bb399335.aspx

Consejos para mejorar el rendimiento de tu Entity Framework (III)

Deshabitar el control de cambios.

Una instancia ObjectContext  crea un  objeto ObjectStateEntry que se encargará de seguir los cambios que se hacen en las entidades (las propiedades se marcan como modificadas y pero también se guardan los valores originales).
Este seguimiento provoca una carga, que es innecesaria si el objeto no se va a modificar o si se envian los datos a través de un webservice, y que puede reducirse usando la opción MergeOption.NoTracking.

Deshabitar la Concurrencia Optimista. 

Linq to SQL admite el control de simultaneidad optimista (técnica que antes de relizar un cambio investiga si otras transacciones han cambiado los valores de una fila antes de que se envíen los cambios, y que bloquea el registro para evitar los conflictos de simultaneidad).
Sin embargo, si la aplicación no tiene problemas de concurrencia, o si puede ejecutarse en modo "la última actualización gana", entonces la carga generada por el UpdateCheck es innecesaria. Por eso se especifica UpdateCheck.Never para deshabilitar la concurrencia en Linq to SQL.

Consejos para mejorar el rendimiento de tu Entity Framework (II)

Pre-generar las vistas.

Para que una consulta se pueda ejecutar con un Entity Data Model (EDM), el Entity Framework (EF) genera un conjunto de vistas que se utilizan para tener acceso a la base de datos.

El EF genera vistas las primera vez que se ejecuta una consulta, y se mantiene durante toda la vida de  la instancia del ObjectContext, pero este proceso es el más costoso de toda la consulta, ya que tarda aproximadamente un 50% de la operación total.  Por eso, EF premite generar previamente estas vistas e incluirlas en el proyecto compilado, aunque esto también tiene una desventaja, y es que implica que hay que tener las vistas sincronizadas con los cambios del modelo de datos.

Las vistas pre-generadas se validan en tiempo de ejecución para asegurarse de que son coherentes con la versión actual de EDM, pero se puede omitir si el proceso de generación está generando los archivos de asignación y modelo en el directorio de salida (en el Explorador de Modelos, en la ventana propiedades, cambiar la opción "Procesamiento de artefactos de metadatos" a "Copiar en el directorio de resultados" y recompilar).

Para pre-generarlas se usa una herramienta llamada "Generador de EDM", que suele estar en Windows\Microsoft.NET\Framework\v3.5 y se llama EdmGen.exe si no lo encuentras Microsoft facilita su descarga desde aquí).

Para generar las vistas y agregarlas a un proyecto C# se usa esta  herramienta de línea de comandos con un el parámetro de generación de vistas (/mode:ViewGeneration).

"%windir%\Microsoft.NET\Framework\v3.5\EdmGen.exe"     /mode:ViewGeneration     /language:CSharp     /nologo     "/inssdl:MyEntityModel.ssdl"     "/incsdl:MyEntityModel.csdl"     "/inmsl:MyEntityModel.msl"     "/outviews:MyEntityModel.Views.cs"

También se puede hacer desde la Consola de comandos del VS2008 (Inicio -> todos los programas -> MSVS2008 -> VS Tools -> VS2008 Command Prompt).

O bien:

  1. En el Explorador de soluciones, seleccione el proyecto para el que desea especificar el evento de generación.
  2. En el menú Proyecto, haga clic en Propiedades.
  3. Seleccione la ficha Generar eventos.
  4. la ventana Línea de comandos del evento anterior a la compilación, agregue el "evento anterior a la generación" añadir el comando anterior (en azul) sin saltos de línea.
  5. Genere la solución.

Para volver a agregar los archivos de asignación y modelo como recursos incrustados para los proyectos ASP.NET, modifique el parámetro Metadata del atributo connectionString (puede encontrar más información sobre cómo hacer esto en esta entrada anterior de este blog)

Via: How to: Pre-Generate Views to Improve Query Performance (Entity Framework)

Consejos para mejorar el rendimiento de tu Entity Framework (I)

Entity Framework es un conjunto de tecnologías de ADO.NET que posibilita el desarrollo de aplicaciones de software orientadas a datos, que permite a los programadores elevar el nivel de abstracción cuando se trabaja con datos (menos código de acceso, menos mantenimiento, estructura más manejable, y persistencia). Para ello, Entity Framework (EF a partir de ahora),  define objetos a partir del modelo de datos.
Cuanto mayor sea nuestra base de datos y más datos, tablas e interconexiones entre ellas, más importante será mantener una buena política en cuanto al uso del EF, para que su eficiencia y rendimiento sean óptimos. Durante las próximas semanas enumeraré  algunas buenas prácticas que todos deberíamos tener en cuenta cuando generemos nuestro Entity.

Cadenas de conexión 
#; VS 2008; Entity Framework; VS 2010
Cuando se crean los Object Queries se recupera la cadena de conexión del archivo .config, sin embargo, hay otra forma de suministrársela: cuando se instancia el ObjectContext (en la propiedad ConnectionString del objeto EntityConnection).
Ubicación de los metadatos y asignaciones del EDM

Los archivos de metadatos y asignaciones del EDM, frecuentemente se desarrollan ir en el mismo directorio del archivo ejecutable de la aplicación, sin embargo, para mejorar el rendimiento, podemos incluidos la solución. Para ello:
1) Abre el proyecto con el EF
2) Abrir el EDMX.
3) Hacer click en el fondo, y abrir la ventana de propiedades.
4) Cambiar la propiedad Procesamiento de artefactos de metadatos (Metadata Artifact Processing) a Incrustado en el ensamblado de salida (Embed in Output Assemply).
Los recursos embebidos se especifican en la propiedad Metadata del connectionString, de la siguiente forma:

 Metadata=res://<assemblyFullName>/<resourceName>

Además, es mejor no usar caracteres comodín (*) en la propiedad assemblyFullName para evitar que el EF haga una búsqueda de los recursos en todos los lugares especificados.

Debajo, en un extracto de un web.config, se puede ver un ejemplo del parámetro connectionString, con la propiedad metadata, en la que se especifica el ensamblado con nombre

OSK.Core.EntityModel.dll
<connectionStrings>   <add name="OSKEntities"   connectionString="metadata=res://OSK.Core.EntityModel,Version=1.0.0.0,           Culture=neutral,   PublicKeyToken=null/;           provider=System.Data.SqlClient; provider connection string=&quot;
Data Source=DEIMOS;Initial Catalog=OSK;
          Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

Via: Connection Strings (Entity Framework)