EF 4.1 y la pre-generación de vistas
La verdad es que el tema de la pregeneración de vistas ya es algo sobre lo que he hablado bastante en mi blog, la ultima entrada creo que fué esta referida a temas de rendimiento, algo sobre lo que afecta mucho, sobre todo cuando hablamos de modelos grandes ( en los tiempos de carga y/o de primeras operaciones ). Generalmente, la forma más sencilla de precompilar estas vistas era por medio de una plantilla de T4, como la siguiente, que se encargaba de leer la información de nuestro modelo EDM y generar para esta información un archivo .cs que contenía la pregeneración de vistas y que incluiamos en la compilación de nuestra unidad de trabajo. Si utilizamos Code First, esta plantilla ya no nos servirá ( por lo menos totalmente ) puesto que ya no tenemos un fichero EDMX sobre el que esto trabaje y por lo tanto no tenemos forma de pregenerar estas vistas tan facilmente. Para ayudarnos, el equipo de EF hace un tiempo que saco una herramienta conocida como EF 4.1 Power Tool la cual dispone de una opción para hacernos este trabajo muy sencillo como se puede observar en la siguiente figura, en la que vemos un nuevo menú contextual dentro de Visual Studio con la opción “Optimize Entity Data Model”, opción que automáticamente agregarla un fichero de precompilación de vistas en el proyecto en el que estemos.

Para el que no quiera usar esta herramienta, esta en CTP1 y a muchos no les gusta ( no nos gusta ) instalar betas y demás en nuestros equipos de trabajo real, podemos utilizar el siguiente fragmento de código, para pregenerar las vistas, lógicamente, esta opción es mucho más “manual” que la anterior, pero aunque sea por un mero ejercicio práctico aquí os lo dejo.
public static class EFF4Helper
{
public static string PregenerateViews<TContext>(TContext context)
where TContext : DbContext
{
using (MemoryStream stream = new MemoryStream())
using (XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings() { Encoding = new UTF8Encoding() }))
{
EdmxWriter.WriteEdmx(context, writer);
stream.Seek(0, SeekOrigin.Begin);
return GenerateViews(stream);
}
}
static String GenerateViews(Stream edmxContent)
{
String generatedViews = String.Empty;
try
{
using (StreamWriter writer = new StreamWriter(new MemoryStream()))
{
XmlReader csdlReader = null;
XmlReader mslReader = null;
XmlReader ssdlReader = null;
GetConceptualMappingAndStorageReaders(edmxContent, out csdlReader, out mslReader, out ssdlReader);
EdmItemCollection edmItems = new EdmItemCollection(new XmlReader[] { csdlReader });
StoreItemCollection storeItems = new StoreItemCollection(new XmlReader[] { ssdlReader });
StorageMappingItemCollection mappingItems = new StorageMappingItemCollection(edmItems, storeItems, new XmlReader[] { mslReader });
EntityViewGenerator viewGenerator = new EntityViewGenerator();
viewGenerator.LanguageOption = LanguageOption.GenerateCSharpCode;
IList<EdmSchemaError> errors = viewGenerator.GenerateViews(mappingItems, writer);
foreach (EdmSchemaError e in errors)
{
Console.WriteLine("Error:{0}", e.ToString());
}
MemoryStream memStream = writer.BaseStream as MemoryStream;
generatedViews = Encoding.UTF8.GetString(memStream.ToArray());
}
}
catch (Exception ex)
{
Console.WriteLine("Error:{0}", ex.ToString());
}
return generatedViews;
}
static void GetConceptualMappingAndStorageReaders(Stream edmx, out XmlReader csdlReader, out XmlReader mslReader, out XmlReader ssdlReader)
{
csdlReader = null;
mslReader = null;
ssdlReader = null;
XNamespace edmxns = "http://schemas.microsoft.com/ado/2008/10/edmx";
XNamespace csdlns = "http://schemas.microsoft.com/ado/2008/09/edm";
XNamespace mslns = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";
XNamespace ssdlns = "http://schemas.microsoft.com/ado/2009/02/edm/ssdl";
XDocument edmxDoc = XDocument.Load(edmx);
if (edmxDoc != null)
{
XElement edmxNode = edmxDoc.Element(edmxns + "Edmx");
if (edmxNode != null)
{
XElement runtimeNode = edmxNode.Element(edmxns + "Runtime");
if (runtimeNode != null)
{
// Create XmlReader over CSDL in EDMX
XElement conceptualModelsNode = runtimeNode.Element(edmxns + "ConceptualModels");
if (conceptualModelsNode != null)
{
XElement csdlContent = conceptualModelsNode.Element(csdlns + "Schema");
if (csdlContent != null)
{
csdlReader = csdlContent.CreateReader();
}
}
// Create XmlReader over MSL in EDMX
XElement mappingsNode = runtimeNode.Element(edmxns + "Mappings");
if (mappingsNode != null)
{
XElement mslContent = mappingsNode.Element(mslns + "Mapping");
if (mslContent != null)
{
mslReader = mslContent.CreateReader();
}
}
// Create XmlReader over SSDL in EDMX
XElement storageModelsNode = runtimeNode.Element(edmxns + "StorageModels");
if (storageModelsNode != null)
{
XElement ssdlContent = storageModelsNode.Element(ssdlns + "Schema");
if (ssdlContent != null)
{
ssdlReader = ssdlContent.CreateReader();
}
}
}
}
}
}
}
Saludos
Unai