Следующее расширение работает для EF6 alpha2, но перестало работать с альфа3 с нулевым исключением ссылки. Выдающимся утверждением является EdmxWriter.WriteEdmx (..)EntityFramework 6.0.0-alpha3 - EdmxWriter.WriteEdmx() не работает после обновления до alpha3 из alpha2
Представление предварительного просмотра выполняется в контексте кода.
Как добиться предварительного генерации представлений с использованием EF6 alpha3?
public static PreGeneratedViews PreGenerateViews<T>(this T dbContext) where T : DbContext
{
Trace.TraceInformation("PreGenerating views");
//define ef collections
EdmItemCollection edmItemCollection = null;
StoreItemCollection storeItemCollection = null;
StorageMappingItemCollection mappingItemCollection = null;
//get ef collections
GetItemCollections(
GetEdmx(dbContext),
out edmItemCollection,
out storeItemCollection,
out mappingItemCollection);
IList<EdmSchemaError> errors = null;
//get the generated views
Dictionary<string, string> extentViews = GetExtentViews(mappingItemCollection, out errors);
//return the pregenerated views as string (xml document)
return new PreGeneratedViews
{
EdmEntityContainerName = edmItemCollection.GetItems<EntityContainer>().Single().Name,
StoreEntityContainerName = storeItemCollection.GetItems<EntityContainer>().Single().Name,
HashOverMappingClosure =
ReflectionHelper.GetMappingClosureHash(edmItemCollection.EdmVersion,
mappingItemCollection),
HashOverAllExtentViews =
ReflectionHelper.GenerateHashForAllExtentViewsContent(edmItemCollection.EdmVersion,
extentViews),
ViewCount = extentViews.Count,
Views = CreateViews(extentViews),
ViewsEmbeddedResourceName =
string.Format("DbContextViews{0}.xml", Guid.NewGuid().ToString("N")),
};
}
private static XDocument GetEdmx(DbContext dbContext)
{
var ms = new MemoryStream();
using (XmlWriter writer = XmlWriter.Create(ms))
{
EdmxWriter.WriteEdmx(dbContext, writer);
}
ms.Position = 0;
return XDocument.Load(ms);
}
private static void SplitEdmx(XDocument edmx, out XmlReader csdlReader, out XmlReader ssdlReader,
out XmlReader mslReader)
{
// xml namespace agnostic to make it work with any version of Entity Framework
XNamespace edmxNs = edmx.Root.Name.Namespace;
XElement storageModels = edmx.Descendants(edmxNs + "StorageModels").Single();
XElement conceptualModels = edmx.Descendants(edmxNs + "ConceptualModels").Single();
XElement mappings = edmx.Descendants(edmxNs + "Mappings").Single();
ssdlReader = storageModels.Elements().Single(e => e.Name.LocalName == "Schema").CreateReader();
csdlReader = conceptualModels.Elements().Single(e => e.Name.LocalName == "Schema").CreateReader();
mslReader = mappings.Elements().Single(e => e.Name.LocalName == "Mapping").CreateReader();
}
private static void GetItemCollections(XDocument edmx, out EdmItemCollection edmItemCollection,
out StoreItemCollection storeItemCollection,
out StorageMappingItemCollection mappingItemCollection)
{
// extract csdl, ssdl and msl artifacts from the Edmx
XmlReader csdlReader, ssdlReader, mslReader;
SplitEdmx(edmx, out csdlReader, out ssdlReader, out mslReader);
// Initialize item collections
edmItemCollection = new EdmItemCollection(new[] {csdlReader});
storeItemCollection = new StoreItemCollection(new[] {ssdlReader});
mappingItemCollection = new StorageMappingItemCollection(edmItemCollection, storeItemCollection,
new[] {mslReader});
}
private static Dictionary<string, string> GetExtentViews(StorageMappingItemCollection mappingItemCollection,
out IList<EdmSchemaError> errors)
{
Dictionary<EntitySetBase, string> views = ReflectionHelper.GenerateViews(mappingItemCollection, out errors);
if (errors != null && errors.Any())
{
return null;
}
var extentViews = new Dictionary<string, string>(views.Count);
foreach (var kvp in views)
{
extentViews.Add(
GetExtentFullName(kvp.Key),
kvp.Value.Replace("\r\n", "\n")); // replace accounts for Xml new line normalization
}
return extentViews;
}
private static string GetExtentFullName(EntitySetBase entitySet)
{
return string.Format("{0}.{1}", entitySet.EntityContainer.Name, entitySet.Name);
}
private static string CreateViews(Dictionary<string, string> extentViews)
{
var sb = new StringBuilder();
//var embeddedViewsFileName = Path.ChangeExtension(Host.TemplateFile, "xml");
using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings
{
Indent = true,
Encoding = Encoding.UTF8
}))
{
writer.WriteStartElement("views");
foreach (var kvp in extentViews)
{
writer.WriteStartElement("view");
writer.WriteAttributeString("extent", kvp.Key);
writer.WriteCData(kvp.Value);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
return sb.ToString();
}
#region Nested type: ReflectionHelper
private static class ReflectionHelper
{
private static readonly Assembly efAssembly = typeof (StorageMappingItemCollection).Assembly;
private static readonly MethodInfo generateViewsMethodInfo =
typeof (StorageMappingItemCollection).GetMethod("GenerateEntitySetViews",
BindingFlags.NonPublic | BindingFlags.Instance);
private static readonly MethodInfo getMappingClosureHashMethodInfo =
efAssembly.GetType("System.Data.Entity.Core.Mapping.MetadataMappingHasherVisitor", true)
.GetMethod("GetMappingClosureHash", BindingFlags.Static | BindingFlags.NonPublic);
private static readonly MethodInfo generateHashForAllExtentViewsContentMethodInfo =
efAssembly.GetType("System.Data.Entity.Core.Common.Utils.MetadataHelper", true)
.GetMethod("GenerateHashForAllExtentViewsContent", BindingFlags.Static | BindingFlags.NonPublic);
public static Dictionary<EntitySetBase, string> GenerateViews(
StorageMappingItemCollection mappingItemCollection, out IList<EdmSchemaError> errors)
{
errors = null;
return
(Dictionary<EntitySetBase, string>)
generateViewsMethodInfo.Invoke(mappingItemCollection, new object[] {errors});
}
public static string GetMappingClosureHash(double schemaVersion,
StorageMappingItemCollection mappingItemCollection)
{
return (string) getMappingClosureHashMethodInfo.Invoke(
null,
new object[]
{
schemaVersion,
// CodeFirst currently creates always one entity container
mappingItemCollection.GetItems<GlobalItem>().Single(
i => i.GetType().Name == "StorageEntityContainerMapping")
});
}
public static string GenerateHashForAllExtentViewsContent(double schemaVersion,
Dictionary<string, string> extentViews)
{
return (string) generateHashForAllExtentViewsContentMethodInfo.Invoke(
null,
new object[] {schemaVersion, extentViews});
}
}
StackTrace является следующее:
NullReferenceException
- по адресу: System.Data.Entity.Edm.Serialization.EdmSerializationVisitor.VisitEdmAssociationSet (AssociationSet пункта)
- по адресу: системы. Data.Entity.Edm.EdmModelVisitor.VisitCollection [T] (IEnumerable
1 collection, Action
1 visitMethod) - по адресу: System.Data.Ent ity.Edm.EdmModelVisitor.VisitAssociationSets (EntityContainer контейнер, IEnumerable`1 associationSets)
- по адресу: System.Data.Entity.Edm.EdmModelVisitor.VisitEdmEntityContainer (EntityContainer пункта)
- на: System.Data.Entity.Edm.Serialization .EdmSerializationVisitor.VisitEdmEntityContainer (EntityContainer элемент)
- по адресу: System.Data.Entity.Edm.EdmModelVisitor.VisitCollection [T] (IEnumerable
1 collection, Action
1 visitMethod) - по адресу: System.Data.Entity.Edm.EdmModelVisitor.VisitEntityContainers (IEnumerable`1 entityContainers)
- по адресу: System.Data.Entity.Edm.EdmModelVisitor.VisitEdmModel (EdmM Одел пункт)
- по адресу: System.Data.Entity.Edm.Serialization.EdmSerializationVisitor.Visit (EdmModel edmModel, String NamespaceName, поставщик String, String providerManifestToken)
- по адресу: System.Data.Entity.Edm.Serialization.EdmSerializationVisitor .Visit (EdmModel edmModel, поставщик String, String providerManifestToken)
- по адресу: System.Data.Entity.Edm.Serialization.SsdlSerializer.Serialize (EdmModel dbDatabase, поставщика String, String providerManifestToken, XmlWriter XMLWriter, булева serializeDefaultNullability)
- на : System.Data.Entity.ModelConfiguration.Edm.Serialization.EdmxSerializer.WriteEdmxRuntime()
- на: System.Data.Entity.ModelConfiguration.Edm.Serialization.EdmxSerializer.Serialize (DbDatabaseMapping databaseMapping, DbProviderInfo providerInfo, XmlWriter XMLWriter)
- по адресу: System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx (модель DbModel, XmlWriter писатель)
- по адресу: System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx (DbContext контекст, XmlWriter писатель)
- по адресу: ** .DbContextPreGenerateViewExtension.GetEdmx (DbContext DbContext)
Спасибо!
Лучше сообщить об этом как об ошибке в [EF's codeplex site] (http://entityframework.codeplex.com/). –
для справки: новый [выпуск] (http://entityframework.codeplex.com/workitem/917) был отправлен на [codeplex] (http://entityframework.codeplex.com/) – csizo
Я думаю, что это происходит только для некоторые модели - можете ли вы показать свою модель? – Pawel