MetadataItemSerializer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntityDesign / Design / System / Data / Entity / Design / Common / MetadataItemSerializer.cs / 1305376 / MetadataItemSerializer.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Data.Common; 
using System.Collections.Generic;
using System.Text;
using System.Data.Metadata.Edm;
using System.Reflection; 
using System.Diagnostics;
using System.Xml; 
using System.Globalization; 
using System.IO;
using System.Data.Entity.Design.SsdlGenerator; 
using System.Linq;

namespace System.Data.Entity.Design.Common
{ 
    /// 
    /// This class is reponsible for serailizing Edm Metadata out to the appropriate file .csdl or .ssdl 
    ///  
    internal class MetadataItemSerializer
    { 
        public static readonly EdmType NoSpecificTypeSentinal = MetadataItem.GetBuiltInType(BuiltInTypeKind.EdmType);

        private bool _isModel;
        private ErrorsLookup _errorsLookup; 
        private XmlWriter _writer;
        private Version _schemaVersion; 
 
        private MetadataItemSerializer(XmlWriter writer, bool isModel, ErrorsLookup errorsLookup, Version schemaVersion)
        { 
            _writer = writer;
            _isModel = isModel;
            _errorsLookup = errorsLookup;
            _schemaVersion = schemaVersion; 
        }
 
        public class ErrorsLookup : Dictionary> { } 

        internal readonly string EdmNamespace = "Edm"; 

        public static void WriteXml(XmlWriter writer, ItemCollection collection, string namespaceToWrite, Version schemaVersion, params KeyValuePair [] xmlPrefixToNamespaces)
        {
            WriteXml(writer, collection, namespaceToWrite, new ErrorsLookup(), new List(), null, null, schemaVersion, xmlPrefixToNamespaces); 
        }
 
        internal static void WriteXml(XmlWriter writer, ItemCollection collection, string namespaceToWrite, ErrorsLookup errorsLookup, List commentedOutItems, string provider, string providerManifestToken, Version schemaVersion, params KeyValuePair[] xmlPrefixToNamespaces) 
        {
            Debug.Assert(writer != null, "writer parameter is null"); 
            Debug.Assert(collection != null, "collection parameter is null");
            Debug.Assert(errorsLookup != null, "errorsLookup parameter is null");
            Debug.Assert(!string.IsNullOrEmpty(namespaceToWrite), "namespaceToWrite parameter is null or empty");
 
            MetadataItemSerializer serializer = new MetadataItemSerializer(writer, collection.DataSpace == DataSpace.CSpace, errorsLookup, schemaVersion);
 
            serializer.ValidateNamespace(namespaceToWrite); 
            serializer.WriteSchemaElement(namespaceToWrite, provider, providerManifestToken, xmlPrefixToNamespaces);
            serializer.WriteErrorsComment(NoSpecificTypeSentinal); 
            foreach (EntityContainer item in collection.GetItems())
            {
                serializer.WriteEntityContainerElement(item);
            } 

            foreach (EdmType type in collection.GetItems()) 
            { 
                // is it in the right space (c or s)
                // does it have the right namespace? 
                if (type.NamespaceName == namespaceToWrite)
                {
                    serializer.WriteTypeElement(type);
                } 
            }
 
            if(commentedOutItems.Count > 0) 
            {
                StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); 
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;
                settings.OmitXmlDeclaration = true;
                // we can have more than one commented out type 
                // which will look like multiple root elements, so this is a fragment
                settings.ConformanceLevel = ConformanceLevel.Fragment; 
                XmlWriter commentWriter = XmlWriter.Create(stringWriter, settings); 
                MetadataItemSerializer commmentSerializer = new MetadataItemSerializer(commentWriter, collection.DataSpace == DataSpace.CSpace, errorsLookup, schemaVersion);
                foreach (EdmType type in commentedOutItems) 
                {
                    commmentSerializer.WriteTypeElement(type);
                }
                commentWriter.Flush(); 
                //This is not the cleanest thing to do but XmlTextWriter
                //does not allow writing xml comment characters while writing a comment. 
                //and since we know exactly the string we write, this is pretty safe. 
                string comment = RemoveXmlCommentCharacters(stringWriter);
                writer.WriteComment(comment); 
            }
            writer.WriteEndElement();
        }
 
        private static string RemoveXmlCommentCharacters(StringWriter stringWriter)
        { 
            string comment = stringWriter.GetStringBuilder().ToString(); 
            while (comment.Contains(XmlConstants.XmlCommentStartString))
            { 
                comment = comment.Replace(XmlConstants.XmlCommentStartString, String.Empty);
            }
            while (comment.Contains(XmlConstants.XmlCommentEndString))
            { 
                comment = comment.Replace(XmlConstants.XmlCommentEndString, String.Empty);
            } 
            return comment; 
        }
 
        private void ValidateNamespace(string namespaceToWrite)
        {
            if (EdmItemCollection.IsSystemNamespace(MetadataItem.EdmProviderManifest, namespaceToWrite))
            { 
                throw EDesignUtil.EdmReservedNamespace(namespaceToWrite);
            } 
        } 

        private void WriteTypeElement(EdmType type) 
        {
            WriteErrorsComment(type);
            switch (type.BuiltInTypeKind)
            { 
                case BuiltInTypeKind.EntityType:
                    WriteEntityTypeElement((EntityType)type); 
                    break; 
                case BuiltInTypeKind.AssociationType:
                    WriteAssociationTypeElement((AssociationType)type); 
                    break;
                case BuiltInTypeKind.EdmFunction:
                    // skip user defined functions for csdl
                    if (!_isModel) 
                    {
                        WriteFunctionElement((EdmFunction)type); 
                    } 
                    break;
                case BuiltInTypeKind.ComplexType: 
                    WriteComplexTypeElement((ComplexType)type);
                    break;
                default:
                    throw EDesignUtil.NonSerializableType(type.BuiltInTypeKind); 
            }
        } 
 
        private void WriteFunctionElement(EdmFunction function)
        { 
            _writer.WriteStartElement(XmlConstants.Function);
            _writer.WriteAttributeString(XmlConstants.Name, function.Name);
            if (function.ReturnParameter != null)
            { 
                _writer.WriteAttributeString(XmlConstants.ReturnType, GetFullName(function.ReturnParameter.TypeUsage.EdmType));
            } 
            _writer.WriteAttributeString(XmlConstants.AggregateAttribute, GetAttributeValueString(function.AggregateAttribute)); 
            _writer.WriteAttributeString(XmlConstants.BuiltInAttribute, GetAttributeValueString(function.BuiltInAttribute));
            _writer.WriteAttributeString(XmlConstants.NiladicFunction, GetAttributeValueString(function.NiladicFunctionAttribute)); 
            _writer.WriteAttributeString(XmlConstants.IsComposable, GetAttributeValueString(function.IsComposableAttribute));
            _writer.WriteAttributeString(XmlConstants.ParameterTypeSemantics, GetAttributeValueString(function.ParameterTypeSemanticsAttribute));

            if (function.StoreFunctionNameAttribute != null) 
            {
                _writer.WriteAttributeString(XmlConstants.StoreFunctionName, function.StoreFunctionNameAttribute); 
            } 

            if(function.CommandTextAttribute != null) 
            {
                _writer.WriteAttributeString(XmlConstants.CommandText, function.CommandTextAttribute);
            }
 
            if (function.Schema != null)
            { 
                _writer.WriteAttributeString(XmlConstants.Schema, function.Schema); 
            }
 
            foreach (FunctionParameter parameter in function.Parameters)
            {
                WriteFunctionParameterElement(parameter);
            } 

            _writer.WriteEndElement(); 
        } 

        private void WriteFunctionParameterElement(FunctionParameter parameter) 
        {
            _writer.WriteStartElement(XmlConstants.Parameter);
            _writer.WriteAttributeString(XmlConstants.Name, parameter.Name);
            _writer.WriteAttributeString(XmlConstants.TypeAttribute, GetFullName(parameter.TypeUsage.EdmType)); 
            _writer.WriteAttributeString(XmlConstants.Mode, GetAttributeValueString(parameter.Mode));
            _writer.WriteEndElement(); 
        } 

 
        private void WriteComplexTypeElement(ComplexType complexType)
        {
            _writer.WriteStartElement(XmlConstants.ComplexType);
            _writer.WriteAttributeString(XmlConstants.Name, complexType.Name); 
            if (complexType.BaseType != null)
            { 
                _writer.WriteAttributeString(XmlConstants.BaseType, GetFullName(complexType.BaseType)); 
            }
 
            foreach (EdmMember member in complexType.GetDeclaredOnlyMembers())
            {
                WritePropertyElement(member);
            } 
            _writer.WriteEndElement();
        } 
 
        private void WriteAssociationTypeElement(AssociationType associationType)
        { 
            _writer.WriteStartElement(XmlConstants.Association);
            _writer.WriteAttributeString(XmlConstants.Name, associationType.Name);
            foreach (RelationshipEndMember end in associationType.RelationshipEndMembers)
            { 
                WriteRelationshipEndElement(end);
            } 
 
            foreach (ReferentialConstraint constraint in associationType.ReferentialConstraints)
            { 
                WriteReferentialConstraintElement(constraint);
            }

            _writer.WriteEndElement(); 
        }
 
        private void WriteReferentialConstraintElement(ReferentialConstraint constraint) 
        {
            _writer.WriteStartElement(XmlConstants.ReferentialConstraint); 
            WriteReferentialConstraintRoleElement(XmlConstants.PrincipalRole, constraint.FromRole, constraint.FromProperties);
            WriteReferentialConstraintRoleElement(XmlConstants.DependentRole, constraint.ToRole, constraint.ToProperties);
            _writer.WriteEndElement();
        } 

        private void WriteReferentialConstraintRoleElement(string nodeName, RelationshipEndMember end, IList properties) 
        { 
            // Generate the principal and dependent role nodes
            _writer.WriteStartElement(nodeName); 
            _writer.WriteAttributeString(XmlConstants.Role, end.Name);
            for (int i = 0; i < properties.Count; i++)
            {
                _writer.WriteStartElement(XmlConstants.PropertyRef); 
                _writer.WriteAttributeString(XmlConstants.Name, properties[i].Name);
                _writer.WriteEndElement(); 
            } 
            _writer.WriteEndElement();
        } 

        private void WriteRelationshipEndElement(RelationshipEndMember end)
        {
            _writer.WriteStartElement(XmlConstants.End); 
            _writer.WriteAttributeString(XmlConstants.Role, end.Name);
 
            string typeName = GetFullName(((RefType)end.TypeUsage.EdmType).ElementType); 
            _writer.WriteAttributeString(XmlConstants.TypeAttribute, typeName);
            _writer.WriteAttributeString(XmlConstants.Multiplicity, GetXmlMultiplicity(end.RelationshipMultiplicity)); 
            if (end.DeleteBehavior != OperationAction.None)
            {
                WriteOperationActionElement(XmlConstants.OnDelete, end.DeleteBehavior);
            } 
            _writer.WriteEndElement();
        } 
 
        private void WriteOperationActionElement(string elementName, OperationAction operationAction)
        { 
            _writer.WriteStartElement(elementName);
            _writer.WriteAttributeString(XmlConstants.Action, operationAction.ToString());
            _writer.WriteEndElement();
        } 

        private string GetXmlMultiplicity(RelationshipMultiplicity relationshipMultiplicity) 
        { 
            switch(relationshipMultiplicity)
            { 
                case RelationshipMultiplicity.Many:
                    return "*";
                case RelationshipMultiplicity.One:
                    return "1"; 
                case RelationshipMultiplicity.ZeroOrOne:
                    return "0..1"; 
                default: 
                    Debug.Fail("Did you add a new RelationshipMultiplicity?");
                    return string.Empty; 
            }
        }

        private void WriteEntityTypeElement(EntityType entityType) 
        {
            _writer.WriteStartElement(XmlConstants.EntityType); 
            _writer.WriteAttributeString(XmlConstants.Name, entityType.Name); 
            if (entityType.BaseType != null)
            { 
                _writer.WriteAttributeString(XmlConstants.BaseType, GetFullName(entityType.BaseType));
            }

            if (entityType.Abstract) 
            {
                _writer.WriteAttributeString(XmlConstants.Abstract, XmlConstants.True); 
            } 

            if (entityType.KeyMembers.Count != 0 && 
                entityType.KeyMembers[0].DeclaringType == entityType) // they are declared on this entity
            {
                _writer.WriteStartElement(XmlConstants.Key);
                for (int i = 0; i < entityType.KeyMembers.Count; i++) 
                {
                    _writer.WriteStartElement(XmlConstants.PropertyRef); 
                    _writer.WriteAttributeString(XmlConstants.Name, entityType.KeyMembers[i].Name); 
                    _writer.WriteEndElement();
                } 
                _writer.WriteEndElement();
            }

            foreach (EdmProperty member in entityType.GetDeclaredOnlyMembers()) 
            {
                WritePropertyElement(member); 
            } 

            foreach (NavigationProperty navigationProperty in entityType.NavigationProperties ) 
            {
                if (navigationProperty.DeclaringType == entityType)
                {
                    WriteNavigationPropertyElement(navigationProperty); 
                }
            } 
            _writer.WriteEndElement(); 
        }
 
        private void WriteErrorsComment(EdmType type)
        {
            List errors;
            if (_errorsLookup.TryGetValue(type, out errors)) 
            {
                Debug.Assert(errors.Count > 0, "how did we get an empty errors collection?"); 
 
                StringBuilder builder = new StringBuilder();
                builder.AppendLine(Strings.MetadataItemErrorsFoundDuringGeneration); 
                foreach (EdmSchemaError error in errors)
                {
                    builder.AppendLine(error.ToString());
                } 
                _writer.WriteComment(builder.ToString());
            } 
        } 

        private void WriteNavigationPropertyElement(NavigationProperty member) 
        {
            _writer.WriteStartElement(XmlConstants.NavigationProperty);
            _writer.WriteAttributeString(XmlConstants.Name, member.Name);
            _writer.WriteAttributeString(XmlConstants.Relationship, member.RelationshipType.FullName); 
            _writer.WriteAttributeString(XmlConstants.FromRole, member.FromEndMember.Name);
            _writer.WriteAttributeString(XmlConstants.ToRole, member.ToEndMember.Name); 
            _writer.WriteEndElement(); 
        }
 
        private void WritePropertyElement(EdmMember member)
        {
            _writer.WriteStartElement(XmlConstants.Property);
            _writer.WriteAttributeString(XmlConstants.Name, member.Name); 
            _writer.WriteAttributeString(XmlConstants.TypeAttribute, GetTypeName(member.TypeUsage));
            WritePropertyTypeFacets(member.TypeUsage); 
 
            //
            // Generate "annotation:StoreGeneratedPattern="Identity"" for model schema 
            //
            if (_isModel && member.MetadataProperties.Contains(DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.StoreGeneratedPattern))
            {
                _writer.WriteAttributeString( 
                    TranslateFacetNameToAttributeName(
                        DesignXmlConstants.StoreGeneratedPattern), 
                    DesignXmlConstants.EdmAnnotationNamespace, 
                    GetAttributeValueString(
                        member.MetadataProperties[DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.StoreGeneratedPattern].Value)); 
            }

            _writer.WriteEndElement();
        } 

        private void WritePropertyTypeFacets(TypeUsage typeUsage) 
        { 
            // we need to use the facets for this particular provider, not the ones that they type
            // may have been converted to (think CSDL types converted to provider types) 
            EdmType type = GetEdmType(typeUsage);
            IEnumerable providerDescriptions = GetAssociatedFacetDescriptions(type);

            foreach (Facet facet in typeUsage.Facets) 
            {
                FacetDescription providerFacetDescription = null; 
                if (IsSpecialFacet(facet)) 
                {
                    providerFacetDescription = facet.Description; 
                }
                else
                {
                    foreach (FacetDescription description in providerDescriptions) 
                    {
                        if (description.FacetName == facet.Name) 
                        { 
                            providerFacetDescription = description;
                            break; 
                        }
                    }
                }
 
                //
                // Don't emit this facet if we shouldn't 
                // 
                if (SkipFacet(facet, providerFacetDescription))
                { 
                    continue;
                }

                // 
                // Special case for MaxLength facet value of "Max"
                // 
                if (_isModel && 
                    type.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType)
                { 
                    PrimitiveType primitiveType = (PrimitiveType)type;

                    if ((primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.String ||
                         primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Binary) && 
                        facet.Name == DbProviderManifest.MaxLengthFacetName &&
                        Helper.IsUnboundedFacetValue(facet)) 
                    { 
                        _writer.WriteAttributeString(TranslateFacetNameToAttributeName(facet.Name), XmlConstants.Max);
                        continue; 
                    }
                }

                _writer.WriteAttributeString(TranslateFacetNameToAttributeName(facet.Name), GetAttributeValueString(facet.Value)); 
            }
        } 
 

        private string TranslateFacetNameToAttributeName(string facetName) 
        {
            if(DbProviderManifest.DefaultValueFacetName == facetName)
            {
                return XmlConstants.DefaultValueAttribute; 
            }
 
            return facetName; 
        }
 
        /// 
        /// Should this facet be skipped ?
        /// A facet should be skipped if it satsifies one of the following
        ///   - the providerFacetDescription is null - (ie) the provider knows of no such facet 
        ///   - the facetDescription indicates that the facet must have a constant value
        ///   - the facet value is null 
        ///   - the facet value is the default value for the facet, and the facet is not required 
        ///   - we're emitting a model schema, and the facet in question is one of the following
        ///       - MaxLength, FixedLength, Unicode, Collation, Precision, Scale, DateTimeKind 
        /// 
        /// the facet in question
        /// facet description in the provider
        /// true, if the facet should be skipped 
        private bool SkipFacet(Facet facet, FacetDescription providerFacetDescription)
        { 
            // 
            // if the provider doesn't recognize it, it will complain
            // when it sees it; so don't put it in 
            //
            if (providerFacetDescription == null)
            {
                return true; 
            }
            // skip it if it is constant for the current provider 
            if (providerFacetDescription.IsConstant) 
            {
                return true; 
            }

            //
            // Null facets can and should be omitted 
            //
            if (facet.Value == null) 
            { 
                return true;
            } 

            //
            // skip if it is not required, and has the default value
            // 
            if (!providerFacetDescription.IsRequired &&
                facet.Value.Equals(providerFacetDescription.DefaultValue)) 
            { 
                return true;
            } 

            return false;
        }
 
        private bool IsSpecialFacet(Facet facet)
        { 
            if(_isModel) 
            {
                return (facet.Name == "ClientAutoGenerated" || 
                        facet.Name == EdmProviderManifest.ConcurrencyModeFacetName ||
                        facet.Name == XmlConstants.StoreGeneratedPattern ||
                        facet.Name == DbProviderManifest.CollationFacetName);
            } 
            else
            { 
                return (facet.Name == EdmProviderManifest.StoreGeneratedPatternFacetName || 
                        facet.Name == DbProviderManifest.CollationFacetName);
            } 
        }

        private IEnumerable GetAssociatedFacetDescriptions(EdmType type)
        { 
            MethodInfo mi = typeof(EdmType).GetMethod("GetAssociatedFacetDescriptions", BindingFlags.NonPublic | BindingFlags.Instance);
            Debug.Assert(mi != null, "Method GetAssociatedFacetDescriptions is missing"); 
            return (IEnumerable)mi.Invoke(type, new object[0]); 
        }
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")]
        private string GetAttributeValueString(object o)
        {
            if (o.GetType() == typeof(bool)) 
            {
                return o.ToString().ToLower(CultureInfo.InvariantCulture); 
            } 
            else
            { 
                return o.ToString();
            }
        }
 
        private EdmType GetEdmType(TypeUsage typeUsage)
        { 
            if (_isModel) 
            {
                return GetModelType(typeUsage.EdmType); 
            }
            else
            {
                return typeUsage.EdmType; 
            }
        } 
        private string GetTypeName(TypeUsage typeUsage) 
        {
            EdmType type = GetEdmType(typeUsage); 
            if (type.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType)
            {
                return type.Name;
            } 
            else
            { 
                return GetFullName(type); 
            }
        } 

        private EdmType GetModelType(EdmType edmType)
        {
            if (edmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType) 
            {
                return edmType; 
            } 

            while (edmType != null && edmType.NamespaceName != EdmNamespace) 
            {
                edmType = edmType.BaseType;
            }
 
            return edmType;
        } 
 
        private void WriteSchemaElement(string schemaNamespace, string provider, string providerManifestToken, params KeyValuePair[] xmlPrefixToNamespaces)
        { 
            string xmlNamespace = EntityFrameworkVersions.GetSchemaNamespace(_schemaVersion, _isModel ? DataSpace.CSpace : DataSpace.SSpace);
            _writer.WriteStartElement(XmlConstants.Schema, xmlNamespace);
            _writer.WriteAttributeString(XmlConstants.Namespace, schemaNamespace);
            _writer.WriteAttributeString(XmlConstants.Alias, "Self"); 
            if (!_isModel)
            { 
                if (!string.IsNullOrEmpty(provider)) 
                {
                    _writer.WriteAttributeString(XmlConstants.Provider, provider); 
                }

                if (!string.IsNullOrEmpty(providerManifestToken))
                { 
                    _writer.WriteAttributeString(XmlConstants.ProviderManifestToken, providerManifestToken);
                } 
            } 

            // write out the extra xml namespaces and their pretty prefix 
            foreach (KeyValuePair xmlPrefixToNamespace in xmlPrefixToNamespaces)
            {
                // see http://www.w3.org/TR/2006/REC-xml-names-20060816/
                _writer.WriteAttributeString("xmlns", xmlPrefixToNamespace.Key, null, xmlPrefixToNamespace.Value); 
            }
        } 
 
        private void WriteEntityContainerElement(EntityContainer container)
        { 
            _writer.WriteStartElement(XmlConstants.EntityContainer);
            _writer.WriteAttributeString(XmlConstants.Name, container.Name);

            // 
            // Generate "annotation:LazyLoadingEnabled="true"" for model schema
            // 
            if (_isModel && container.MetadataProperties.Contains(DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.LazyLoadingEnabled)) 
            {
                _writer.WriteAttributeString( 
                    TranslateFacetNameToAttributeName(
                        DesignXmlConstants.LazyLoadingEnabled),
                    DesignXmlConstants.EdmAnnotationNamespace,
                    GetAttributeValueString( 
                        container.MetadataProperties[DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.LazyLoadingEnabled].Value));
            } 
 
            foreach (EntitySetBase set in container.BaseEntitySets)
            { 
                switch (set.BuiltInTypeKind)
                {
                    case BuiltInTypeKind.EntitySet:
                        WriteEntitySetElement((EntitySet)set); 
                        break;
                    case BuiltInTypeKind.AssociationSet: 
                        WriteAssociationSetElement((AssociationSet)set); 
                        break;
                    default: 
                        throw EDesignUtil.NonSerializableType(set.BuiltInTypeKind);
                }
            }
 

            _writer.WriteEndElement(); 
        } 

        private void WriteAssociationSetElement(AssociationSet associationSet) 
        {
            _writer.WriteStartElement(XmlConstants.AssociationSet);
            _writer.WriteAttributeString(XmlConstants.Name, associationSet.Name);
            _writer.WriteAttributeString(XmlConstants.Association, GetFullName(associationSet.ElementType)); 

            foreach (AssociationSetEnd end in associationSet.AssociationSetEnds) 
            { 
                WriteAssociationSetEndElement(end);
            } 
            _writer.WriteEndElement();
        }

        private void WriteAssociationSetEndElement(AssociationSetEnd end) 
        {
            _writer.WriteStartElement(XmlConstants.End); 
            _writer.WriteAttributeString(XmlConstants.Role, end.Name); 
            _writer.WriteAttributeString(XmlConstants.EntitySet, end.EntitySet.Name);
            _writer.WriteEndElement(); 
        }

        private void WriteEntitySetElement(EntitySet entitySet)
        { 
            _writer.WriteStartElement(XmlConstants.EntitySet);
            _writer.WriteAttributeString(XmlConstants.Name, entitySet.Name); 
            _writer.WriteAttributeString(XmlConstants.EntityType, GetFullName(entitySet.ElementType)); 
            WriteExtendedPropertyAttributes(entitySet);
 
            MetadataProperty property;
            if (entitySet.MetadataProperties.TryGetValue(XmlConstants.DefiningQuery, false, out property) &&
                property.Value != null)
            { 
                _writer.WriteStartElement(XmlConstants.DefiningQuery);
                _writer.WriteString(entitySet.DefiningQuery); 
                _writer.WriteEndElement(); 
            }
            else 
            {
                if (entitySet.MetadataProperties.TryGetValue(XmlConstants.Schema, false, out property) &&
                    property.Value != null)
                { 
                    _writer.WriteAttributeString(property.Name, property.Value.ToString());
                } 
 
                if (entitySet.MetadataProperties.TryGetValue(XmlConstants.Table, false, out property) &&
                    property.Value != null) 
                {
                    _writer.WriteAttributeString(property.Name, property.Value.ToString());
                }
            } 

 
            _writer.WriteEndElement(); 
        }
 
        private void WriteExtendedPropertyAttributes(MetadataItem item)
        {
            foreach (MetadataProperty property in item.MetadataProperties.Where(p => p.PropertyKind == PropertyKind.Extended))
            { 
                string xmlNamespace, attributeName;
                if (MetadataUtil.TrySplitExtendedMetadataPropertyName(property.Name, out xmlNamespace, out attributeName)) 
                { 
                    _writer.WriteAttributeString(attributeName, xmlNamespace, property.Value.ToString());
                } 
            }
        }

        private string GetFullName(EdmType type) 
        {
            string namespaceName = null; 
            string name; 
            string modifierFormat = null;
 
            if (type.BuiltInTypeKind == BuiltInTypeKind.CollectionType)
            {
                type = ((CollectionType)type).TypeUsage.EdmType;
                modifierFormat = "Collection({0})"; 
            }
 
            if (type.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType) 
            {
                // primitive types are not required to be qualified 
                name = type.Name;
            }
            else
            { 
                namespaceName = type.NamespaceName;
                name = type.Name; 
            } 

            string qualifiedTypeName; 
            if (namespaceName == null)
            {
                qualifiedTypeName = name;
            } 
            else
            { 
                qualifiedTypeName = namespaceName + "." + name; 
            }
 
            if (modifierFormat != null)
            {
                qualifiedTypeName = string.Format(CultureInfo.InvariantCulture, modifierFormat, qualifiedTypeName);
            } 

            return qualifiedTypeName; 
         } 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Data.Common; 
using System.Collections.Generic;
using System.Text;
using System.Data.Metadata.Edm;
using System.Reflection; 
using System.Diagnostics;
using System.Xml; 
using System.Globalization; 
using System.IO;
using System.Data.Entity.Design.SsdlGenerator; 
using System.Linq;

namespace System.Data.Entity.Design.Common
{ 
    /// 
    /// This class is reponsible for serailizing Edm Metadata out to the appropriate file .csdl or .ssdl 
    ///  
    internal class MetadataItemSerializer
    { 
        public static readonly EdmType NoSpecificTypeSentinal = MetadataItem.GetBuiltInType(BuiltInTypeKind.EdmType);

        private bool _isModel;
        private ErrorsLookup _errorsLookup; 
        private XmlWriter _writer;
        private Version _schemaVersion; 
 
        private MetadataItemSerializer(XmlWriter writer, bool isModel, ErrorsLookup errorsLookup, Version schemaVersion)
        { 
            _writer = writer;
            _isModel = isModel;
            _errorsLookup = errorsLookup;
            _schemaVersion = schemaVersion; 
        }
 
        public class ErrorsLookup : Dictionary> { } 

        internal readonly string EdmNamespace = "Edm"; 

        public static void WriteXml(XmlWriter writer, ItemCollection collection, string namespaceToWrite, Version schemaVersion, params KeyValuePair [] xmlPrefixToNamespaces)
        {
            WriteXml(writer, collection, namespaceToWrite, new ErrorsLookup(), new List(), null, null, schemaVersion, xmlPrefixToNamespaces); 
        }
 
        internal static void WriteXml(XmlWriter writer, ItemCollection collection, string namespaceToWrite, ErrorsLookup errorsLookup, List commentedOutItems, string provider, string providerManifestToken, Version schemaVersion, params KeyValuePair[] xmlPrefixToNamespaces) 
        {
            Debug.Assert(writer != null, "writer parameter is null"); 
            Debug.Assert(collection != null, "collection parameter is null");
            Debug.Assert(errorsLookup != null, "errorsLookup parameter is null");
            Debug.Assert(!string.IsNullOrEmpty(namespaceToWrite), "namespaceToWrite parameter is null or empty");
 
            MetadataItemSerializer serializer = new MetadataItemSerializer(writer, collection.DataSpace == DataSpace.CSpace, errorsLookup, schemaVersion);
 
            serializer.ValidateNamespace(namespaceToWrite); 
            serializer.WriteSchemaElement(namespaceToWrite, provider, providerManifestToken, xmlPrefixToNamespaces);
            serializer.WriteErrorsComment(NoSpecificTypeSentinal); 
            foreach (EntityContainer item in collection.GetItems())
            {
                serializer.WriteEntityContainerElement(item);
            } 

            foreach (EdmType type in collection.GetItems()) 
            { 
                // is it in the right space (c or s)
                // does it have the right namespace? 
                if (type.NamespaceName == namespaceToWrite)
                {
                    serializer.WriteTypeElement(type);
                } 
            }
 
            if(commentedOutItems.Count > 0) 
            {
                StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); 
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;
                settings.OmitXmlDeclaration = true;
                // we can have more than one commented out type 
                // which will look like multiple root elements, so this is a fragment
                settings.ConformanceLevel = ConformanceLevel.Fragment; 
                XmlWriter commentWriter = XmlWriter.Create(stringWriter, settings); 
                MetadataItemSerializer commmentSerializer = new MetadataItemSerializer(commentWriter, collection.DataSpace == DataSpace.CSpace, errorsLookup, schemaVersion);
                foreach (EdmType type in commentedOutItems) 
                {
                    commmentSerializer.WriteTypeElement(type);
                }
                commentWriter.Flush(); 
                //This is not the cleanest thing to do but XmlTextWriter
                //does not allow writing xml comment characters while writing a comment. 
                //and since we know exactly the string we write, this is pretty safe. 
                string comment = RemoveXmlCommentCharacters(stringWriter);
                writer.WriteComment(comment); 
            }
            writer.WriteEndElement();
        }
 
        private static string RemoveXmlCommentCharacters(StringWriter stringWriter)
        { 
            string comment = stringWriter.GetStringBuilder().ToString(); 
            while (comment.Contains(XmlConstants.XmlCommentStartString))
            { 
                comment = comment.Replace(XmlConstants.XmlCommentStartString, String.Empty);
            }
            while (comment.Contains(XmlConstants.XmlCommentEndString))
            { 
                comment = comment.Replace(XmlConstants.XmlCommentEndString, String.Empty);
            } 
            return comment; 
        }
 
        private void ValidateNamespace(string namespaceToWrite)
        {
            if (EdmItemCollection.IsSystemNamespace(MetadataItem.EdmProviderManifest, namespaceToWrite))
            { 
                throw EDesignUtil.EdmReservedNamespace(namespaceToWrite);
            } 
        } 

        private void WriteTypeElement(EdmType type) 
        {
            WriteErrorsComment(type);
            switch (type.BuiltInTypeKind)
            { 
                case BuiltInTypeKind.EntityType:
                    WriteEntityTypeElement((EntityType)type); 
                    break; 
                case BuiltInTypeKind.AssociationType:
                    WriteAssociationTypeElement((AssociationType)type); 
                    break;
                case BuiltInTypeKind.EdmFunction:
                    // skip user defined functions for csdl
                    if (!_isModel) 
                    {
                        WriteFunctionElement((EdmFunction)type); 
                    } 
                    break;
                case BuiltInTypeKind.ComplexType: 
                    WriteComplexTypeElement((ComplexType)type);
                    break;
                default:
                    throw EDesignUtil.NonSerializableType(type.BuiltInTypeKind); 
            }
        } 
 
        private void WriteFunctionElement(EdmFunction function)
        { 
            _writer.WriteStartElement(XmlConstants.Function);
            _writer.WriteAttributeString(XmlConstants.Name, function.Name);
            if (function.ReturnParameter != null)
            { 
                _writer.WriteAttributeString(XmlConstants.ReturnType, GetFullName(function.ReturnParameter.TypeUsage.EdmType));
            } 
            _writer.WriteAttributeString(XmlConstants.AggregateAttribute, GetAttributeValueString(function.AggregateAttribute)); 
            _writer.WriteAttributeString(XmlConstants.BuiltInAttribute, GetAttributeValueString(function.BuiltInAttribute));
            _writer.WriteAttributeString(XmlConstants.NiladicFunction, GetAttributeValueString(function.NiladicFunctionAttribute)); 
            _writer.WriteAttributeString(XmlConstants.IsComposable, GetAttributeValueString(function.IsComposableAttribute));
            _writer.WriteAttributeString(XmlConstants.ParameterTypeSemantics, GetAttributeValueString(function.ParameterTypeSemanticsAttribute));

            if (function.StoreFunctionNameAttribute != null) 
            {
                _writer.WriteAttributeString(XmlConstants.StoreFunctionName, function.StoreFunctionNameAttribute); 
            } 

            if(function.CommandTextAttribute != null) 
            {
                _writer.WriteAttributeString(XmlConstants.CommandText, function.CommandTextAttribute);
            }
 
            if (function.Schema != null)
            { 
                _writer.WriteAttributeString(XmlConstants.Schema, function.Schema); 
            }
 
            foreach (FunctionParameter parameter in function.Parameters)
            {
                WriteFunctionParameterElement(parameter);
            } 

            _writer.WriteEndElement(); 
        } 

        private void WriteFunctionParameterElement(FunctionParameter parameter) 
        {
            _writer.WriteStartElement(XmlConstants.Parameter);
            _writer.WriteAttributeString(XmlConstants.Name, parameter.Name);
            _writer.WriteAttributeString(XmlConstants.TypeAttribute, GetFullName(parameter.TypeUsage.EdmType)); 
            _writer.WriteAttributeString(XmlConstants.Mode, GetAttributeValueString(parameter.Mode));
            _writer.WriteEndElement(); 
        } 

 
        private void WriteComplexTypeElement(ComplexType complexType)
        {
            _writer.WriteStartElement(XmlConstants.ComplexType);
            _writer.WriteAttributeString(XmlConstants.Name, complexType.Name); 
            if (complexType.BaseType != null)
            { 
                _writer.WriteAttributeString(XmlConstants.BaseType, GetFullName(complexType.BaseType)); 
            }
 
            foreach (EdmMember member in complexType.GetDeclaredOnlyMembers())
            {
                WritePropertyElement(member);
            } 
            _writer.WriteEndElement();
        } 
 
        private void WriteAssociationTypeElement(AssociationType associationType)
        { 
            _writer.WriteStartElement(XmlConstants.Association);
            _writer.WriteAttributeString(XmlConstants.Name, associationType.Name);
            foreach (RelationshipEndMember end in associationType.RelationshipEndMembers)
            { 
                WriteRelationshipEndElement(end);
            } 
 
            foreach (ReferentialConstraint constraint in associationType.ReferentialConstraints)
            { 
                WriteReferentialConstraintElement(constraint);
            }

            _writer.WriteEndElement(); 
        }
 
        private void WriteReferentialConstraintElement(ReferentialConstraint constraint) 
        {
            _writer.WriteStartElement(XmlConstants.ReferentialConstraint); 
            WriteReferentialConstraintRoleElement(XmlConstants.PrincipalRole, constraint.FromRole, constraint.FromProperties);
            WriteReferentialConstraintRoleElement(XmlConstants.DependentRole, constraint.ToRole, constraint.ToProperties);
            _writer.WriteEndElement();
        } 

        private void WriteReferentialConstraintRoleElement(string nodeName, RelationshipEndMember end, IList properties) 
        { 
            // Generate the principal and dependent role nodes
            _writer.WriteStartElement(nodeName); 
            _writer.WriteAttributeString(XmlConstants.Role, end.Name);
            for (int i = 0; i < properties.Count; i++)
            {
                _writer.WriteStartElement(XmlConstants.PropertyRef); 
                _writer.WriteAttributeString(XmlConstants.Name, properties[i].Name);
                _writer.WriteEndElement(); 
            } 
            _writer.WriteEndElement();
        } 

        private void WriteRelationshipEndElement(RelationshipEndMember end)
        {
            _writer.WriteStartElement(XmlConstants.End); 
            _writer.WriteAttributeString(XmlConstants.Role, end.Name);
 
            string typeName = GetFullName(((RefType)end.TypeUsage.EdmType).ElementType); 
            _writer.WriteAttributeString(XmlConstants.TypeAttribute, typeName);
            _writer.WriteAttributeString(XmlConstants.Multiplicity, GetXmlMultiplicity(end.RelationshipMultiplicity)); 
            if (end.DeleteBehavior != OperationAction.None)
            {
                WriteOperationActionElement(XmlConstants.OnDelete, end.DeleteBehavior);
            } 
            _writer.WriteEndElement();
        } 
 
        private void WriteOperationActionElement(string elementName, OperationAction operationAction)
        { 
            _writer.WriteStartElement(elementName);
            _writer.WriteAttributeString(XmlConstants.Action, operationAction.ToString());
            _writer.WriteEndElement();
        } 

        private string GetXmlMultiplicity(RelationshipMultiplicity relationshipMultiplicity) 
        { 
            switch(relationshipMultiplicity)
            { 
                case RelationshipMultiplicity.Many:
                    return "*";
                case RelationshipMultiplicity.One:
                    return "1"; 
                case RelationshipMultiplicity.ZeroOrOne:
                    return "0..1"; 
                default: 
                    Debug.Fail("Did you add a new RelationshipMultiplicity?");
                    return string.Empty; 
            }
        }

        private void WriteEntityTypeElement(EntityType entityType) 
        {
            _writer.WriteStartElement(XmlConstants.EntityType); 
            _writer.WriteAttributeString(XmlConstants.Name, entityType.Name); 
            if (entityType.BaseType != null)
            { 
                _writer.WriteAttributeString(XmlConstants.BaseType, GetFullName(entityType.BaseType));
            }

            if (entityType.Abstract) 
            {
                _writer.WriteAttributeString(XmlConstants.Abstract, XmlConstants.True); 
            } 

            if (entityType.KeyMembers.Count != 0 && 
                entityType.KeyMembers[0].DeclaringType == entityType) // they are declared on this entity
            {
                _writer.WriteStartElement(XmlConstants.Key);
                for (int i = 0; i < entityType.KeyMembers.Count; i++) 
                {
                    _writer.WriteStartElement(XmlConstants.PropertyRef); 
                    _writer.WriteAttributeString(XmlConstants.Name, entityType.KeyMembers[i].Name); 
                    _writer.WriteEndElement();
                } 
                _writer.WriteEndElement();
            }

            foreach (EdmProperty member in entityType.GetDeclaredOnlyMembers()) 
            {
                WritePropertyElement(member); 
            } 

            foreach (NavigationProperty navigationProperty in entityType.NavigationProperties ) 
            {
                if (navigationProperty.DeclaringType == entityType)
                {
                    WriteNavigationPropertyElement(navigationProperty); 
                }
            } 
            _writer.WriteEndElement(); 
        }
 
        private void WriteErrorsComment(EdmType type)
        {
            List errors;
            if (_errorsLookup.TryGetValue(type, out errors)) 
            {
                Debug.Assert(errors.Count > 0, "how did we get an empty errors collection?"); 
 
                StringBuilder builder = new StringBuilder();
                builder.AppendLine(Strings.MetadataItemErrorsFoundDuringGeneration); 
                foreach (EdmSchemaError error in errors)
                {
                    builder.AppendLine(error.ToString());
                } 
                _writer.WriteComment(builder.ToString());
            } 
        } 

        private void WriteNavigationPropertyElement(NavigationProperty member) 
        {
            _writer.WriteStartElement(XmlConstants.NavigationProperty);
            _writer.WriteAttributeString(XmlConstants.Name, member.Name);
            _writer.WriteAttributeString(XmlConstants.Relationship, member.RelationshipType.FullName); 
            _writer.WriteAttributeString(XmlConstants.FromRole, member.FromEndMember.Name);
            _writer.WriteAttributeString(XmlConstants.ToRole, member.ToEndMember.Name); 
            _writer.WriteEndElement(); 
        }
 
        private void WritePropertyElement(EdmMember member)
        {
            _writer.WriteStartElement(XmlConstants.Property);
            _writer.WriteAttributeString(XmlConstants.Name, member.Name); 
            _writer.WriteAttributeString(XmlConstants.TypeAttribute, GetTypeName(member.TypeUsage));
            WritePropertyTypeFacets(member.TypeUsage); 
 
            //
            // Generate "annotation:StoreGeneratedPattern="Identity"" for model schema 
            //
            if (_isModel && member.MetadataProperties.Contains(DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.StoreGeneratedPattern))
            {
                _writer.WriteAttributeString( 
                    TranslateFacetNameToAttributeName(
                        DesignXmlConstants.StoreGeneratedPattern), 
                    DesignXmlConstants.EdmAnnotationNamespace, 
                    GetAttributeValueString(
                        member.MetadataProperties[DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.StoreGeneratedPattern].Value)); 
            }

            _writer.WriteEndElement();
        } 

        private void WritePropertyTypeFacets(TypeUsage typeUsage) 
        { 
            // we need to use the facets for this particular provider, not the ones that they type
            // may have been converted to (think CSDL types converted to provider types) 
            EdmType type = GetEdmType(typeUsage);
            IEnumerable providerDescriptions = GetAssociatedFacetDescriptions(type);

            foreach (Facet facet in typeUsage.Facets) 
            {
                FacetDescription providerFacetDescription = null; 
                if (IsSpecialFacet(facet)) 
                {
                    providerFacetDescription = facet.Description; 
                }
                else
                {
                    foreach (FacetDescription description in providerDescriptions) 
                    {
                        if (description.FacetName == facet.Name) 
                        { 
                            providerFacetDescription = description;
                            break; 
                        }
                    }
                }
 
                //
                // Don't emit this facet if we shouldn't 
                // 
                if (SkipFacet(facet, providerFacetDescription))
                { 
                    continue;
                }

                // 
                // Special case for MaxLength facet value of "Max"
                // 
                if (_isModel && 
                    type.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType)
                { 
                    PrimitiveType primitiveType = (PrimitiveType)type;

                    if ((primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.String ||
                         primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Binary) && 
                        facet.Name == DbProviderManifest.MaxLengthFacetName &&
                        Helper.IsUnboundedFacetValue(facet)) 
                    { 
                        _writer.WriteAttributeString(TranslateFacetNameToAttributeName(facet.Name), XmlConstants.Max);
                        continue; 
                    }
                }

                _writer.WriteAttributeString(TranslateFacetNameToAttributeName(facet.Name), GetAttributeValueString(facet.Value)); 
            }
        } 
 

        private string TranslateFacetNameToAttributeName(string facetName) 
        {
            if(DbProviderManifest.DefaultValueFacetName == facetName)
            {
                return XmlConstants.DefaultValueAttribute; 
            }
 
            return facetName; 
        }
 
        /// 
        /// Should this facet be skipped ?
        /// A facet should be skipped if it satsifies one of the following
        ///   - the providerFacetDescription is null - (ie) the provider knows of no such facet 
        ///   - the facetDescription indicates that the facet must have a constant value
        ///   - the facet value is null 
        ///   - the facet value is the default value for the facet, and the facet is not required 
        ///   - we're emitting a model schema, and the facet in question is one of the following
        ///       - MaxLength, FixedLength, Unicode, Collation, Precision, Scale, DateTimeKind 
        /// 
        /// the facet in question
        /// facet description in the provider
        /// true, if the facet should be skipped 
        private bool SkipFacet(Facet facet, FacetDescription providerFacetDescription)
        { 
            // 
            // if the provider doesn't recognize it, it will complain
            // when it sees it; so don't put it in 
            //
            if (providerFacetDescription == null)
            {
                return true; 
            }
            // skip it if it is constant for the current provider 
            if (providerFacetDescription.IsConstant) 
            {
                return true; 
            }

            //
            // Null facets can and should be omitted 
            //
            if (facet.Value == null) 
            { 
                return true;
            } 

            //
            // skip if it is not required, and has the default value
            // 
            if (!providerFacetDescription.IsRequired &&
                facet.Value.Equals(providerFacetDescription.DefaultValue)) 
            { 
                return true;
            } 

            return false;
        }
 
        private bool IsSpecialFacet(Facet facet)
        { 
            if(_isModel) 
            {
                return (facet.Name == "ClientAutoGenerated" || 
                        facet.Name == EdmProviderManifest.ConcurrencyModeFacetName ||
                        facet.Name == XmlConstants.StoreGeneratedPattern ||
                        facet.Name == DbProviderManifest.CollationFacetName);
            } 
            else
            { 
                return (facet.Name == EdmProviderManifest.StoreGeneratedPatternFacetName || 
                        facet.Name == DbProviderManifest.CollationFacetName);
            } 
        }

        private IEnumerable GetAssociatedFacetDescriptions(EdmType type)
        { 
            MethodInfo mi = typeof(EdmType).GetMethod("GetAssociatedFacetDescriptions", BindingFlags.NonPublic | BindingFlags.Instance);
            Debug.Assert(mi != null, "Method GetAssociatedFacetDescriptions is missing"); 
            return (IEnumerable)mi.Invoke(type, new object[0]); 
        }
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")]
        private string GetAttributeValueString(object o)
        {
            if (o.GetType() == typeof(bool)) 
            {
                return o.ToString().ToLower(CultureInfo.InvariantCulture); 
            } 
            else
            { 
                return o.ToString();
            }
        }
 
        private EdmType GetEdmType(TypeUsage typeUsage)
        { 
            if (_isModel) 
            {
                return GetModelType(typeUsage.EdmType); 
            }
            else
            {
                return typeUsage.EdmType; 
            }
        } 
        private string GetTypeName(TypeUsage typeUsage) 
        {
            EdmType type = GetEdmType(typeUsage); 
            if (type.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType)
            {
                return type.Name;
            } 
            else
            { 
                return GetFullName(type); 
            }
        } 

        private EdmType GetModelType(EdmType edmType)
        {
            if (edmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType) 
            {
                return edmType; 
            } 

            while (edmType != null && edmType.NamespaceName != EdmNamespace) 
            {
                edmType = edmType.BaseType;
            }
 
            return edmType;
        } 
 
        private void WriteSchemaElement(string schemaNamespace, string provider, string providerManifestToken, params KeyValuePair[] xmlPrefixToNamespaces)
        { 
            string xmlNamespace = EntityFrameworkVersions.GetSchemaNamespace(_schemaVersion, _isModel ? DataSpace.CSpace : DataSpace.SSpace);
            _writer.WriteStartElement(XmlConstants.Schema, xmlNamespace);
            _writer.WriteAttributeString(XmlConstants.Namespace, schemaNamespace);
            _writer.WriteAttributeString(XmlConstants.Alias, "Self"); 
            if (!_isModel)
            { 
                if (!string.IsNullOrEmpty(provider)) 
                {
                    _writer.WriteAttributeString(XmlConstants.Provider, provider); 
                }

                if (!string.IsNullOrEmpty(providerManifestToken))
                { 
                    _writer.WriteAttributeString(XmlConstants.ProviderManifestToken, providerManifestToken);
                } 
            } 

            // write out the extra xml namespaces and their pretty prefix 
            foreach (KeyValuePair xmlPrefixToNamespace in xmlPrefixToNamespaces)
            {
                // see http://www.w3.org/TR/2006/REC-xml-names-20060816/
                _writer.WriteAttributeString("xmlns", xmlPrefixToNamespace.Key, null, xmlPrefixToNamespace.Value); 
            }
        } 
 
        private void WriteEntityContainerElement(EntityContainer container)
        { 
            _writer.WriteStartElement(XmlConstants.EntityContainer);
            _writer.WriteAttributeString(XmlConstants.Name, container.Name);

            // 
            // Generate "annotation:LazyLoadingEnabled="true"" for model schema
            // 
            if (_isModel && container.MetadataProperties.Contains(DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.LazyLoadingEnabled)) 
            {
                _writer.WriteAttributeString( 
                    TranslateFacetNameToAttributeName(
                        DesignXmlConstants.LazyLoadingEnabled),
                    DesignXmlConstants.EdmAnnotationNamespace,
                    GetAttributeValueString( 
                        container.MetadataProperties[DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.LazyLoadingEnabled].Value));
            } 
 
            foreach (EntitySetBase set in container.BaseEntitySets)
            { 
                switch (set.BuiltInTypeKind)
                {
                    case BuiltInTypeKind.EntitySet:
                        WriteEntitySetElement((EntitySet)set); 
                        break;
                    case BuiltInTypeKind.AssociationSet: 
                        WriteAssociationSetElement((AssociationSet)set); 
                        break;
                    default: 
                        throw EDesignUtil.NonSerializableType(set.BuiltInTypeKind);
                }
            }
 

            _writer.WriteEndElement(); 
        } 

        private void WriteAssociationSetElement(AssociationSet associationSet) 
        {
            _writer.WriteStartElement(XmlConstants.AssociationSet);
            _writer.WriteAttributeString(XmlConstants.Name, associationSet.Name);
            _writer.WriteAttributeString(XmlConstants.Association, GetFullName(associationSet.ElementType)); 

            foreach (AssociationSetEnd end in associationSet.AssociationSetEnds) 
            { 
                WriteAssociationSetEndElement(end);
            } 
            _writer.WriteEndElement();
        }

        private void WriteAssociationSetEndElement(AssociationSetEnd end) 
        {
            _writer.WriteStartElement(XmlConstants.End); 
            _writer.WriteAttributeString(XmlConstants.Role, end.Name); 
            _writer.WriteAttributeString(XmlConstants.EntitySet, end.EntitySet.Name);
            _writer.WriteEndElement(); 
        }

        private void WriteEntitySetElement(EntitySet entitySet)
        { 
            _writer.WriteStartElement(XmlConstants.EntitySet);
            _writer.WriteAttributeString(XmlConstants.Name, entitySet.Name); 
            _writer.WriteAttributeString(XmlConstants.EntityType, GetFullName(entitySet.ElementType)); 
            WriteExtendedPropertyAttributes(entitySet);
 
            MetadataProperty property;
            if (entitySet.MetadataProperties.TryGetValue(XmlConstants.DefiningQuery, false, out property) &&
                property.Value != null)
            { 
                _writer.WriteStartElement(XmlConstants.DefiningQuery);
                _writer.WriteString(entitySet.DefiningQuery); 
                _writer.WriteEndElement(); 
            }
            else 
            {
                if (entitySet.MetadataProperties.TryGetValue(XmlConstants.Schema, false, out property) &&
                    property.Value != null)
                { 
                    _writer.WriteAttributeString(property.Name, property.Value.ToString());
                } 
 
                if (entitySet.MetadataProperties.TryGetValue(XmlConstants.Table, false, out property) &&
                    property.Value != null) 
                {
                    _writer.WriteAttributeString(property.Name, property.Value.ToString());
                }
            } 

 
            _writer.WriteEndElement(); 
        }
 
        private void WriteExtendedPropertyAttributes(MetadataItem item)
        {
            foreach (MetadataProperty property in item.MetadataProperties.Where(p => p.PropertyKind == PropertyKind.Extended))
            { 
                string xmlNamespace, attributeName;
                if (MetadataUtil.TrySplitExtendedMetadataPropertyName(property.Name, out xmlNamespace, out attributeName)) 
                { 
                    _writer.WriteAttributeString(attributeName, xmlNamespace, property.Value.ToString());
                } 
            }
        }

        private string GetFullName(EdmType type) 
        {
            string namespaceName = null; 
            string name; 
            string modifierFormat = null;
 
            if (type.BuiltInTypeKind == BuiltInTypeKind.CollectionType)
            {
                type = ((CollectionType)type).TypeUsage.EdmType;
                modifierFormat = "Collection({0})"; 
            }
 
            if (type.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType) 
            {
                // primitive types are not required to be qualified 
                name = type.Name;
            }
            else
            { 
                namespaceName = type.NamespaceName;
                name = type.Name; 
            } 

            string qualifiedTypeName; 
            if (namespaceName == null)
            {
                qualifiedTypeName = name;
            } 
            else
            { 
                qualifiedTypeName = namespaceName + "." + name; 
            }
 
            if (modifierFormat != null)
            {
                qualifiedTypeName = string.Format(CultureInfo.InvariantCulture, modifierFormat, qualifiedTypeName);
            } 

            return qualifiedTypeName; 
         } 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK