2013-03-04 7 views
0

Следующее расширение работает для 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)

Спасибо!

+0

Лучше сообщить об этом как об ошибке в [EF's codeplex site] (http://entityframework.codeplex.com/). –

+0

для справки: новый [выпуск] (http://entityframework.codeplex.com/workitem/917) был отправлен на [codeplex] (http://entityframework.codeplex.com/) – csizo

+0

Я думаю, что это происходит только для некоторые модели - можете ли вы показать свою модель? – Pawel

ответ

0

Это известный bug в Alpha 3.

+0

как в ссылочной проблеме. Я использую сопоставление наследования на основе атрибутов [Table] ... Любая возможность исправления в окончательной версии EF6, или я должен искать обходной путь в моя модель? спасибо. – csizo

+0

Это будет исправлено, вероятно, в следующей версии. –

1

Я только что представил исправление для рабочего элемента 867 (35852e8392ad). Он должен исправить NRE. Исправление должно быть включено в сегодняшнюю ночную сборку. Можете ли вы дать ему попробовать и сообщить мне, если это устранит проблему?