1 //--------------------------------------------------------------------- 2 // <copyright file="EntityDesignerUtils.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 // 6 // @owner Microsoft 7 // @backupOwner Microsoft 8 //--------------------------------------------------------------------- 9 10 using System.IO; 11 using System.Text; 12 using System.Xml; 13 using System.Data.Metadata.Edm; 14 using System.Data.Mapping; 15 16 namespace System.Data.Entity.Design 17 { 18 internal static class EntityDesignerUtils 19 { 20 internal const string EdmxRootElementName = "Edmx"; 21 internal const string EdmxNamespaceUriV1 = "http://schemas.microsoft.com/ado/2007/06/edmx"; 22 internal const string EdmxNamespaceUriV2 = "http://schemas.microsoft.com/ado/2008/10/edmx"; 23 internal const string EdmxNamespaceUriV3 = "http://schemas.microsoft.com/ado/2009/11/edmx"; 24 25 private static readonly EFNamespaceSet v1Namespaces = new EFNamespaceSet 26 { 27 Edmx = EdmxNamespaceUriV1, 28 Csdl = XmlConstants.ModelNamespace_1, 29 Msl = StorageMslConstructs.NamespaceUriV1, 30 Ssdl = XmlConstants.TargetNamespace_1, 31 }; 32 private static readonly EFNamespaceSet v2Namespaces = new EFNamespaceSet 33 { 34 Edmx = EdmxNamespaceUriV2, 35 Csdl = XmlConstants.ModelNamespace_2, 36 Msl = StorageMslConstructs.NamespaceUriV2, 37 Ssdl = XmlConstants.TargetNamespace_2, 38 }; 39 private static readonly EFNamespaceSet v3Namespaces = new EFNamespaceSet 40 { 41 Edmx = EdmxNamespaceUriV3, 42 Csdl = XmlConstants.ModelNamespace_3, 43 Msl = StorageMslConstructs.NamespaceUriV3, 44 Ssdl = XmlConstants.TargetNamespace_3, 45 }; 46 internal static readonly string _edmxFileExtension = ".edmx"; 47 48 /// <summary> 49 /// Extract the Conceptual, Mapping and Storage nodes from an EDMX input streams, and extract the value of the metadataArtifactProcessing property. 50 /// </summary> 51 /// <param name="edmxInputStream"></param> 52 /// <param name="conceptualSchemaNode"></param> 53 /// <param name="mappingNode"></param> 54 /// <param name="storageSchemaNode"></param> 55 /// ExtractConceptualMappingAndStorageNodes(StreamReader edmxInputStream, out XmlElement conceptualSchemaNode, out XmlElement mappingNode, out XmlElement storageSchemaNode, out string metadataArtifactProcessingValue)56 internal static void ExtractConceptualMappingAndStorageNodes(StreamReader edmxInputStream, 57 out XmlElement conceptualSchemaNode, out XmlElement mappingNode, out XmlElement storageSchemaNode, out string metadataArtifactProcessingValue) 58 { 59 // load up an XML document representing the edmx file 60 XmlDocument xmlDocument = new XmlDocument(); 61 using (var reader = XmlReader.Create(edmxInputStream)) 62 { 63 xmlDocument.Load(reader); 64 } 65 66 EFNamespaceSet set = v3Namespaces; 67 if (xmlDocument.DocumentElement.NamespaceURI == v2Namespaces.Edmx) 68 { 69 set = v2Namespaces; 70 } 71 else if (xmlDocument.DocumentElement.NamespaceURI == v1Namespaces.Edmx) 72 { 73 set = v1Namespaces; 74 } 75 76 XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDocument.NameTable); 77 nsMgr.AddNamespace("edmx", set.Edmx); 78 nsMgr.AddNamespace("edm", set.Csdl); 79 nsMgr.AddNamespace("ssdl", set.Ssdl); 80 nsMgr.AddNamespace("map", set.Msl); 81 82 // find the ConceptualModel Schema node 83 conceptualSchemaNode = (XmlElement)xmlDocument.SelectSingleNode( 84 "/edmx:Edmx/edmx:Runtime/edmx:ConceptualModels/edm:Schema", nsMgr); 85 86 // find the StorageModel Schema node 87 storageSchemaNode = (XmlElement)xmlDocument.SelectSingleNode( 88 "/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema", nsMgr); 89 90 // find the Mapping node 91 mappingNode = (XmlElement)xmlDocument.SelectSingleNode( 92 "/edmx:Edmx/edmx:Runtime/edmx:Mappings/map:Mapping", nsMgr); 93 94 // find the Connection node 95 96 metadataArtifactProcessingValue = String.Empty; 97 XmlNodeList connectionProperties = xmlDocument.SelectNodes( 98 "/edmx:Edmx/edmx:Designer/edmx:Connection/edmx:DesignerInfoPropertySet/edmx:DesignerProperty", nsMgr); 99 if (connectionProperties != null) 100 { 101 foreach (XmlNode propertyNode in connectionProperties) 102 { 103 foreach (XmlAttribute a in propertyNode.Attributes) 104 { 105 // treat attribute names case-sensitive (since it is xml), but attribute value case-insensitive to be accommodating . 106 if (a.Name.Equals("Name", StringComparison.Ordinal) && a.Value.Equals("MetadataArtifactProcessing", StringComparison.OrdinalIgnoreCase)) 107 { 108 foreach (XmlAttribute a2 in propertyNode.Attributes) 109 { 110 if (a2.Name.Equals("Value", StringComparison.Ordinal)) 111 { 112 metadataArtifactProcessingValue = a2.Value; 113 break; 114 } 115 } 116 } 117 } 118 } 119 } 120 } 121 122 // utility method to ensure an XmlElement (containing the C, M or S element 123 // from the Edmx file) is sent out to a stream in the same format OutputXmlElementToStream(XmlElement xmlElement, Stream stream)124 internal static void OutputXmlElementToStream(XmlElement xmlElement, Stream stream) 125 { 126 XmlWriterSettings settings = new XmlWriterSettings(); 127 settings.Encoding = Encoding.UTF8; 128 settings.Indent = true; 129 130 // set up output document 131 XmlDocument outputXmlDoc = new XmlDocument(); 132 XmlNode importedElement = outputXmlDoc.ImportNode(xmlElement, true); 133 outputXmlDoc.AppendChild(importedElement); 134 135 // write out XmlDocument 136 XmlWriter writer = null; 137 try 138 { 139 writer = XmlWriter.Create(stream, settings); 140 outputXmlDoc.WriteTo(writer); 141 } 142 finally 143 { 144 if (writer != null) { writer.Close(); } 145 } 146 } 147 148 private struct EFNamespaceSet 149 { 150 public string Edmx; 151 public string Csdl; 152 public string Msl; 153 public string Ssdl; 154 } 155 } 156 } 157