Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Design / system / Data / EntityModel / EntityClassGenerator.cs / 1407647 / EntityClassGenerator.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.EntityModel; using System.Data.Metadata.Edm; using System.Data.Services.Design.Common; using System.Data.Services.Design.Xml; using System.Diagnostics; using System.IO; using System.Linq; using System.Xml; using System.Xml.Linq; using System.Xml.Schema; using System.Xml.XPath; namespace System.Data.Common.Utils { internal static class EntityUtil { static internal void CheckArgumentNull(T value, string parameterName) where T : class { System.Data.Services.Design.EntityUtil.CheckArgumentNull (value, parameterName); } } } namespace System.Data.Services.Design { internal static class EntityUtil { static internal void CheckArgumentNull (T value, string parameterName) where T : class { EDesignUtil.CheckArgumentNull (value, parameterName); } static internal void CheckStringArgument(string value, string parameterName) { EDesignUtil.CheckStringArgument(value, parameterName); } } /// /// Summary description for CodeGenerator. /// public sealed class EntityClassGenerator { #region Instance Fields private LanguageOption _languageOption = LanguageOption.GenerateCSharpCode; private DataServiceCodeVersion _version = DataServiceCodeVersion.V1; private EdmToObjectNamespaceMap _edmToObjectNamespaceMap = new EdmToObjectNamespaceMap(); private bool _useDataServiceCollection; #if QFE_ENV private bool _useDataServiceCollectionExplicitlySet; private bool _versionExplicitlySet; const string UseDSC_EnvironmentVariable = "dscodegen_usedsc"; const string Version_EnvironmentVariable = "dscodegen_version"; const string Version2Dot0 = "2.0"; const string UseDSCTrue = "1"; #endif #endregion #region Events ////// The event that is raised when a type is generated /// public event EventHandlerOnTypeGenerated; /// /// The event that is raised when a property is generated /// public event EventHandlerOnPropertyGenerated; #endregion #region Public Methods /// /// /// public EntityClassGenerator() { } ////// /// public EntityClassGenerator(LanguageOption languageOption) { _languageOption = EDesignUtil.CheckLanguageOptionArgument(languageOption, "languageOption"); } ////// Get or set the flag that specifies if code generation emits the code necessary for data binding /// public bool UseDataServiceCollection { get { return _useDataServiceCollection; } set { _useDataServiceCollection = value; #if QFE_ENV _useDataServiceCollectionExplicitlySet = true; #endif } } ////// Gets and Sets the WCF Data Service version which the generated code will be compatible with. /// public DataServiceCodeVersion Version { get { return _version; } set { _version = EDesignUtil.CheckDataServiceCodeVersionArgument(value, "value"); #if QFE_ENV _versionExplicitlySet = true; #endif } } ////// Gets and Sets the Language to use for code generation. /// public LanguageOption LanguageOption { get { return _languageOption; } set { _languageOption = EDesignUtil.CheckLanguageOptionArgument(value, "value"); } } ////// Gets the map entries use to customize the namespace of .net types that are generated /// and referenced by the generated code /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] public EdmToObjectNamespaceMap EdmToObjectNamespaceMap { get { return _edmToObjectNamespaceMap; } } public IListGenerateCode(XmlReader sourceReader, string targetFilePath) { EntityUtil.CheckArgumentNull(sourceReader, "sourceReader"); EntityUtil.CheckStringArgument(targetFilePath, "targetPath"); using (LazyTextWriterCreator target = new LazyTextWriterCreator(targetFilePath)) { // we do want to close the file return GenerateCode(sourceReader, target, null); } } /// /// Generate code by reading an EDMX schema from an XmlReader and outputting the code into a TextWriter /// /// Reader with a EDMX schema in it /// Target writer for the generated code /// Prefix to use for generated namespaces ////// Note that the NamespacePrefix is used as the only namespace for types in the same namespace /// as the default container, and as a prefix for the server-provided namespace for everything else. If /// this argument is null, the server-provided namespaces are used for all types. /// ///public IList GenerateCode(XmlReader sourceReader, TextWriter targetWriter, string namespacePrefix) { EntityUtil.CheckArgumentNull(sourceReader, "sourceReader"); EntityUtil.CheckArgumentNull(targetWriter, "targetWriter"); using (LazyTextWriterCreator target = new LazyTextWriterCreator(targetWriter)) { return GenerateCode(sourceReader, target, namespacePrefix); } // does not actually close the targetWriter - that is the caller's responsibility } /// /// Given the specified element in a given namespace, remaps it into a /// /// Element to fit. /// Namespace of element. /// Target namespace. ///and trims elements and attributes that /// don't conform to the schema. /// A new private static XElement FitElementToSchema(XElement element, string schemaNamespace, string targetNamespace) { Debug.Assert(element != null, "element != null"); Debug.Assert(schemaNamespace != null, "schemaNamespace != null"); Debug.Assert(targetNamespace != null, "targetNamespace != null"); Debug.Assert( targetNamespace == XmlConstants.EdmV1dot1Namespace, "targetNamespace == XmlConstants.EdmV1dot1Namespace -- otherwise update CreateTargetSchemaSet to pull other schemas"); XmlSchemaSet schemas = CreateTargetSchemaSet(); XElement result = UpdateNamespaces(element, schemaNamespace, targetNamespace); XNodeSchemaApplier.Apply(schemas, result); return result; } ///that fits the specified . /// Creates an /// Name of the resource to read. ///for the resource in the Entity Framework assembly /// specified by . /// A new [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "caller should Dispose the XmlReader")] private static XmlReader CreateEdmResourceXmlReader(string resourceName) { bool success = false; Stream stream = null; XmlReader result = null; try { stream = typeof(EdmItemCollection).Assembly.GetManifestResourceStream(resourceName); result = XmlReader.Create(stream); success = true; return result; } finally { if (!success) { if (result != null) { result.Close(); } if (stream != null) { stream.Dispose(); } } } } ///instance. Creates the ///that adjusted schemas should target. A new private static XmlSchemaSet CreateTargetSchemaSet() { XmlSchemaSet result = new XmlSchemaSet(); using (XmlReader reader = CreateEdmResourceXmlReader("System.Data.Resources.CodeGenerationSchema.xsd")) { result.Add(null, reader); } using (XmlReader reader = CreateEdmResourceXmlReader("System.Data.Resources.CSDLSchema_1_1.xsd")) { XmlSchema schema = result.Add(null, reader); RemoveReferentialConstraint(schema); AddCustomAttributesToEntityContainer(schema); } XmlSchemaSet result2 = new XmlSchemaSet(); foreach (XmlSchema s in result.Schemas()) { result2.Add(s); } return result2; } ///instance. /// Removes the ReferentialConstraint element from the list of valid children for an association type. /// /// Loadedfor the 1.1 Entity Framework CSDL XSD. private static void RemoveReferentialConstraint(XmlSchema csdlSchema) { Debug.Assert(csdlSchema != null, "csdlSchema != null"); XmlSchemaComplexType associationType = csdlSchema.SchemaTypes[new XmlQualifiedName("TAssociation", csdlSchema.TargetNamespace)] as XmlSchemaComplexType; Debug.Assert(associationType != null, "associationType != null -- otherwise can't find TAssociation - CSDL resource has changed?"); XmlSchemaSequence sequence = associationType.Particle as XmlSchemaSequence; XmlSchemaObject referentialConstraint = null; foreach (XmlSchemaObject item in sequence.Items) { XmlSchemaElement e = item as XmlSchemaElement; if (e.QualifiedName == new XmlQualifiedName("ReferentialConstraint", csdlSchema.TargetNamespace)) { referentialConstraint = e; break; } } Debug.Assert(referentialConstraint != null, "referentialConstraint != null"); sequence.Items.Remove(referentialConstraint); } /// /// Add any attribute to the entity container element in the schema. We need to do /// this, since this was missing from the xsd that got shipped in System.Data.Entity.dll /// in 3.5 SP1. Hence we need to make compensating changes now here. The reason why validating /// against this csd works in edmitemcollection is that they ignore all errors due to elements/attributes /// not in the edm namespace. /// /// Loadedfor the 1.1 Entity Framework CSDL XSD. private static void AddCustomAttributesToEntityContainer(XmlSchema csdlSchema) { Debug.Assert(csdlSchema != null, "csdlSchema != null"); XmlSchemaElement entityContainerElement = csdlSchema.Elements[new XmlQualifiedName("EntityContainer", csdlSchema.TargetNamespace)] as XmlSchemaElement; Debug.Assert(entityContainerElement != null, "entityContainerElement != null -- otherwise can't find EntityContainer element- CSDL resource has changed?"); XmlSchemaComplexType complexType = entityContainerElement.SchemaType as XmlSchemaComplexType; complexType.AnyAttribute = new XmlSchemaAnyAttribute(); complexType.AnyAttribute.Namespace = "##other"; complexType.AnyAttribute.ProcessContents = XmlSchemaContentProcessing.Lax; } /// /// Creates a list of readers for adjusted schemas in the specifed /// Input source for metadata. //// /// A list of readers for Schema elements. ////// These are some processing differences between V1 and V2 metadata. /// /// - V1 processes all Schema elements at any depth. /// - V2 processes only Schema elements that are at the root or under *:Edmx/*:DataServices[1] nodes /// /// - V1 processes Schema elements from known namespaces /// - V2 processes Schema elements from the first Schema's namespace /// /// - V1 ignores the DataServiceVersion attribute on the DataServices element /// - V2 rejects DataServiceVersion attributes with a version that is not 1.0 or 2.0 /// /// The detection hinges on whether all Schema elements belong to 1.1 and 1.0 namespaces; /// if so, we use V1 rules. /// private static ListCreateReaders(XmlReader sourceReader) { Debug.Assert(sourceReader != null, "sourceReader != null"); NameTable nameTable = new NameTable(); XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable); namespaceManager.AddNamespace("m", XmlConstants.DataWebMetadataNamespace); namespaceManager.AddNamespace("edmx", XmlConstants.EdmxNamespace); namespaceManager.AddNamespace("edmv1", XmlConstants.EdmV1Namespace); namespaceManager.AddNamespace("edmv1_1", XmlConstants.EdmV1dot1Namespace); XDocument sourceDocument = XDocument.Load(sourceReader); List schemaElements = new List (); List result = new List (); // Check for V2 schemas. if (TryCreateReadersV2(sourceDocument, schemaElements)) { Debug.Assert(schemaElements.Count > 0, "schemaElements.Count > 0 -- otherwise TryCreateReadersV2 should have returned false"); string schemaNamespace = null; for (int i = 0; i < schemaElements.Count; i++) { if (schemaNamespace == null) { schemaNamespace = schemaElements[i].Name.NamespaceName; } else { if (schemaNamespace != schemaElements[i].Name.NamespaceName) { throw new NotSupportedException(Strings.InvalidMetadataMultipleNamespaces(schemaNamespace, schemaElements[i].Name.NamespaceName)); } } XElement fitted = FitElementToSchema(schemaElements[i], schemaNamespace, XmlConstants.EdmV1dot1Namespace); result.Add(fitted.CreateReader()); } } else { Debug.Assert(result.Count == 0, "result.Count == 0 -- otherwise TryCreateReadesV2 should have returned true"); CreateReadersV1(sourceDocument, namespaceManager, result); } return result; } /// Creates readers as per V1 rules. /// Parsed source document. /// Namespace manager with 'edmv1' and 'edmv1_1' defined. /// List of XmlReaders to populate. ///See comments on CreateReaders for details. private static void CreateReadersV1(XDocument sourceDocument, XmlNamespaceManager namespaceManager, Listreaders) { Debug.Assert(sourceDocument != null, "sourceDocument != null"); Debug.Assert(namespaceManager != null, "namespaceManager != null"); Debug.Assert(readers != null, "readers != null"); Debug.Assert(namespaceManager.HasNamespace("edmv1"), "namespaceManager.HasNamespace('edmv1')"); Debug.Assert(namespaceManager.HasNamespace("edmv1_1"), "namespaceManager.HasNamespace('edmv1_1')"); // Look for 1.0 schema elements foreach (var element in sourceDocument.XPathSelectElements("//edmv1:Schema", namespaceManager)) { readers.Add(element.CreateReader()); } // Look for 1.1 schema elements foreach (var element in sourceDocument.XPathSelectElements("//edmv1_1:Schema", namespaceManager)) { readers.Add(element.CreateReader()); } } /// /// Determines whether the specified /// Name of namespace to check. ///is a known Schema element. /// true if private static bool IsKnownSchemaNamespace(string namespaceName) { return namespaceName == XmlConstants.EdmV1Namespace || namespaceName == XmlConstants.EdmV1dot1Namespace; } ///is a known Schema element; false otherwise. Determines whether the specified /// Element to check. ///is a V2 Schema element. true if ///is a V2 Schema element. /// A V2 Schema is an element with a local name of 'Schema', within a namespace that doesn' /// t belong in the known V1 namespaces. /// private static bool IsSchemaV2(XElement element) { Debug.Assert(element != null, "element != null"); var name = element.Name; return name.LocalName == "Schema" && !IsKnownSchemaNamespace(name.NamespaceName); } ///Tries to create readers according to V2 rules. /// Source document for metadata. /// List of elements to populate with Schema nodes. ///true if schema elements were found according to V2 rules; false otherwise. ///See comments on CreateReaders for details. private static bool TryCreateReadersV2(XDocument sourceDocument, ListschemaElements) { Debug.Assert(sourceDocument != null, "sourceDocument != null"); Debug.Assert(schemaElements != null, "schemaElements != null"); bool result = false; // Check for a root Schema element in a new namespace. var root = sourceDocument.Root; if (IsSchemaV2(root)) { schemaElements.Add(root); result = true; } else { if (root.Name.LocalName == XmlConstants.EdmxElement) { XElement dataServiceElement = root.Elements().Where(e => e.Name.LocalName == XmlConstants.EdmxDataServicesElement).FirstOrDefault(); if (dataServiceElement != null) { XNamespace metadataNs = XmlConstants.DataWebMetadataNamespace; XAttribute version = dataServiceElement.Attributes(metadataNs + XmlConstants.HttpDataServiceVersion).FirstOrDefault(); if (version != null && version.Value != XmlConstants.DataServiceVersion1Dot0 && version.Value != XmlConstants.DataServiceVersion2Dot0) { throw new InvalidOperationException(Strings.InvalidMetadataDataServiceVersion(version.Value)); } schemaElements.AddRange(dataServiceElement.Elements().Where(IsSchemaV2)); result = schemaElements.Count > 0; } } } return result; } /// /// Updates the namespaces under the specified /// Element to update (recursively). /// Old namespace. /// New namespace. ///, changing /// into . /// The updated element. ////// Currently, the updates are in-place, so the returned element is always private static XElement UpdateNamespaces(XElement element, string oldNamespaceName, string newNamespaceName) { Debug.Assert(element != null, "element != null"); Debug.Assert(oldNamespaceName != null, "oldNamespaceName != null"); Debug.Assert(newNamespaceName != null, "newNamespaceName != null"); XNamespace oldNamespace = XNamespace.Get(oldNamespaceName); XNamespace newNamespace = XNamespace.Get(newNamespaceName); Stack. /// /// For valid cases, there will be no qualified CSDL attributes, so those code paths are /// not likely to hit - however the code preserves the namespaces so it can fail /// correctly later on. /// pending = new Stack (); pending.Push(element); do { XElement e = pending.Pop(); if (e.Name.Namespace == oldNamespace) { e.Name = newNamespace.GetName(e.Name.LocalName); } List attributesToReplace = null; foreach (XAttribute attribute in e.Attributes()) { if (attribute.IsNamespaceDeclaration) { if (attribute.Value == oldNamespaceName) { attribute.Value = newNamespaceName; } } else if (attribute.Name.Namespace == oldNamespace || IsOpenTypeAttribute(attribute)) { XNodeSchemaApplier.AppendWithCreation(ref attributesToReplace, attribute); } } if (attributesToReplace != null) { attributesToReplace.Remove(); foreach (XAttribute attribute in attributesToReplace) { if (IsOpenTypeAttribute(attribute)) { XAttribute existingAttribute = e.Attributes().SingleOrDefault(a => a.Name.NamespaceName == XmlConstants.EdmV1dot2Namespace && a.Name.LocalName == attribute.Name.LocalName); if (existingAttribute == null) { e.Add(new XAttribute(XNamespace.Get(XmlConstants.EdmV1dot2Namespace) + attribute.Name.LocalName, attribute.Value)); } else { existingAttribute.Value = attribute.Value; } } else { e.Add(new XAttribute(newNamespace.GetName(attribute.Name.LocalName), attribute.Value)); } } } foreach (var child in e.Elements()) { pending.Push(child); } } while (pending.Count > 0); return element; } private IList GenerateCode(XmlReader sourceReader, LazyTextWriterCreator target, string namespacePrefix) { List readers = CreateReaders(sourceReader); List errors = new List (); EdmItemCollection itemCollection = new EdmItemCollection(readers); #if QFE_ENV _version = _versionExplicitlySet ? _version : GetDataServiceCodeVersionFromEnvironment(); _useDataServiceCollection = _useDataServiceCollectionExplicitlySet ? _useDataServiceCollection : GetUseDataServiceCollectionFromEnvironment(); #endif if (_useDataServiceCollection && _version == DataServiceCodeVersion.V1) { throw new InvalidOperationException(Strings.VersionV1RequiresUseDataServiceCollectionFalse); } // generate code using (ClientApiGenerator generator = new ClientApiGenerator(null, itemCollection, this, errors, namespacePrefix)) { generator.GenerateCode(target); } return errors; } #if QFE_ENV //[System.Security.Permissions.EnvironmentPermission(System.Security.Permissions.SecurityAction.Assert, Read = EntityClassGenerator.Version_EnvironmentVariable)] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2106")] private static DataServiceCodeVersion GetDataServiceCodeVersionFromEnvironment() { return Environment.GetEnvironmentVariable(EntityClassGenerator.Version_EnvironmentVariable) == EntityClassGenerator.Version2Dot0 ? DataServiceCodeVersion.V2 : DataServiceCodeVersion.V1; } //[System.Security.Permissions.EnvironmentPermission(System.Security.Permissions.SecurityAction.Assert, Read = EntityClassGenerator.UseDSC_EnvironmentVariable)] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2106")] private static bool GetUseDataServiceCollectionFromEnvironment() { return Environment.GetEnvironmentVariable(EntityClassGenerator.UseDSC_EnvironmentVariable) == EntityClassGenerator.UseDSCTrue; } #endif /// Checks if the given attribute refers to OpenType attribute. /// Input attribute. ///true if the attribute is OpenType attribute, false otherwise. private static bool IsOpenTypeAttribute(XAttribute attribute) { return attribute.Name.LocalName == XmlConstants.DataWebOpenTypeAttributeName && attribute.Name.Namespace == XNamespace.None; } #endregion #region Event Helpers ////// Helper method that raises the TypeGenerated event /// /// The event arguments passed to the subscriber internal void RaiseTypeGeneratedEvent(TypeGeneratedEventArgs eventArgs) { if (this.OnTypeGenerated != null) { this.OnTypeGenerated(this, eventArgs); } } ////// Helper method that raises the PropertyGenerated event /// /// The event arguments passed to the subscriber internal void RaisePropertyGeneratedEvent(PropertyGeneratedEventArgs eventArgs) { if (this.OnPropertyGenerated != null) { this.OnPropertyGenerated(this, eventArgs); } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- JavaScriptString.cs
- AttachedPropertyInfo.cs
- PaintValueEventArgs.cs
- PersianCalendar.cs
- CatalogPartDesigner.cs
- ValuePattern.cs
- Attributes.cs
- SizeAnimationClockResource.cs
- UICuesEvent.cs
- ElementUtil.cs
- SqlClientPermission.cs
- DNS.cs
- DeclaredTypeValidatorAttribute.cs
- DrawTreeNodeEventArgs.cs
- DocumentApplicationJournalEntry.cs
- ChannelManager.cs
- HttpRawResponse.cs
- PropertyMap.cs
- WebBrowserDocumentCompletedEventHandler.cs
- XmlWriterDelegator.cs
- TargetPerspective.cs
- ServicePoint.cs
- StateInitialization.cs
- DataColumn.cs
- NameObjectCollectionBase.cs
- WindowPattern.cs
- AsyncSerializedWorker.cs
- WindowsIdentity.cs
- OutputScope.cs
- StatusBarDrawItemEvent.cs
- RestClientProxyHandler.cs
- WebPartConnectionsCancelEventArgs.cs
- NetworkInformationPermission.cs
- MetadataFile.cs
- Light.cs
- TypefaceMap.cs
- XmlHierarchicalDataSourceView.cs
- DrawingGroup.cs
- CodeDefaultValueExpression.cs
- BaseDataList.cs
- SRDisplayNameAttribute.cs
- DependencyPropertyAttribute.cs
- SaveRecipientRequest.cs
- MatrixTransform3D.cs
- ValidatingPropertiesEventArgs.cs
- ResourcesGenerator.cs
- VisualSerializer.cs
- WindowInteractionStateTracker.cs
- ControlPersister.cs
- DataIdProcessor.cs
- DrawItemEvent.cs
- Base64Stream.cs
- RequestSecurityTokenResponse.cs
- EventLevel.cs
- TreeBuilder.cs
- TableCell.cs
- XmlElementList.cs
- TimeoutValidationAttribute.cs
- QueryAccessibilityHelpEvent.cs
- XmlSchemaAnnotated.cs
- DataSourceControl.cs
- ViewManager.cs
- UDPClient.cs
- SyndicationItem.cs
- MetadataWorkspace.cs
- XMLSchema.cs
- LocatorGroup.cs
- SettingsAttributes.cs
- ApplicationSecurityInfo.cs
- SvcMapFile.cs
- TraceContext.cs
- LinkConverter.cs
- TextParaClient.cs
- PenThreadWorker.cs
- AppearanceEditorPart.cs
- BitmapEffectOutputConnector.cs
- Merger.cs
- PropertyGridEditorPart.cs
- PolicyManager.cs
- PbrsForward.cs
- InputLangChangeEvent.cs
- Color.cs
- XhtmlConformanceSection.cs
- Size.cs
- ToolStripRenderer.cs
- UrlUtility.cs
- HtmlInputButton.cs
- DependencyProperty.cs
- GridViewCommandEventArgs.cs
- Native.cs
- OpCodes.cs
- WorkflowMessageEventHandler.cs
- FlowDocumentReader.cs
- DeploymentExceptionMapper.cs
- DocumentProperties.cs
- PathHelper.cs
- ObjectPersistData.cs
- GetLedgerRequest.cs
- ListViewHitTestInfo.cs
- ExpandCollapsePattern.cs