EntityType.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Metadata / Edm / EntityType.cs / 1508357 / EntityType.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Collections.Generic; 
using System.Collections.ObjectModel;
using System.Data.Common;
using System.Diagnostics;
using System.Text; 
using System.Threading;
using System.Security.Cryptography; 
using System.Globalization; 

namespace System.Data.Metadata.Edm 
{
    /// 
    /// concrete Representation the Entity Type
    ///  
    public class EntityType : EntityTypeBase
    { 
        #region Constructors 
        /// 
        /// Initializes a new instance of Entity Type 
        /// 
        /// name of the entity type
        /// namespace of the entity type
        /// version of the entity type 
        /// dataspace in which the EntityType belongs to
        /// Thrown if either name, namespace or version arguments are null 
        internal EntityType(string name, string namespaceName, DataSpace dataSpace) 
            : base(name, namespaceName, dataSpace)
        { 
        }

        /// name of the entity type
        /// namespace of the entity type 
        /// version of the entity type
        /// dataspace in which the EntityType belongs to 
        /// members of the entity type [property and navigational property] 
        /// key members for the type
        /// Thrown if either name, namespace or version arguments are null 
        internal EntityType(string name,
                          string namespaceName,
                          DataSpace dataSpace,
                          IEnumerable keyMemberNames, 
                          IEnumerable members)
            : base(name, namespaceName, dataSpace) 
        { 
            //--- first add the properties
            if (null != members) 
            {
                CheckAndAddMembers(members, this);
            }
            //--- second add the key members 
            if (null != keyMemberNames)
            { 
                //Validation should make sure that base type of this type does not have keymembers when this type has keymembers. 
                CheckAndAddKeyMembers(keyMemberNames);
            } 
        }


        #endregion 

        #region Fields 
        /// cached dynamic method to construct a CLR instance 
        private RefType _referenceType;
        private ReadOnlyMetadataCollection _properties; 
        private RowType _keyRow;
        private Dictionary _memberSql;
        private object _memberSqlLock = new object();
        #endregion 

        #region Methods 
        ///  
        /// Returns the kind of the type
        ///  
        public override BuiltInTypeKind BuiltInTypeKind { get { return BuiltInTypeKind.EntityType; } }

        /// 
        /// Validates a EdmMember object to determine if it can be added to this type's 
        /// Members collection. If this method returns without throwing, it is assumed
        /// the member is valid. 
        ///  
        /// The member to validate
        /// Thrown if the member is not a EdmProperty 
        internal override void ValidateMemberForAdd(EdmMember member)
        {
            Debug.Assert(Helper.IsEdmProperty(member) || Helper.IsNavigationProperty(member),
                "Only members of type Property may be added to Entity types."); 
        }
 
        ///  
        /// Get SQL description of a member of this entity type.
        /// Requires: member must belong to this type 
        /// 
        /// Member for which to retrieve SQL
        /// Outputs SQL describing this member
        /// Whether sql is cached for this member 
        internal bool TryGetMemberSql(EdmMember member, out string sql)
        { 
            Debug.Assert(Members.Contains(member)); 
            sql = null;
            return null != _memberSql && _memberSql.TryGetValue(member, out sql); 
        }

        /// 
        /// Sets SQL describing a member of this entity type. 
        /// Requires: member must belong to this type
        ///  
        /// Member for which to set SQL 
        /// SQL describing this member
        internal void SetMemberSql(EdmMember member, string sql) 
        {
            Debug.Assert(Members.Contains(member));

            // initialize dictionary on first use 
            lock (_memberSqlLock)
            { 
                if (null == _memberSql) 
                {
                    _memberSql = new Dictionary(); 
                }

                _memberSql[member] = sql;
            } 
        }
        #endregion 
 
        #region Properties
 
        /// 
        /// Returns the list of Navigation Properties for this entity type
        /// 
        public ReadOnlyMetadataCollection NavigationProperties 
        {
            get 
            { 
                return new FilteredReadOnlyMetadataCollection(
                    ((ReadOnlyMetadataCollection)this.Members), Helper.IsNavigationProperty); 
            }
        }

        ///  
        /// Returns just the properties from the collection
        /// of members on this type 
        ///  
        public ReadOnlyMetadataCollection Properties
        { 
            get
            {
                Debug.Assert(IsReadOnly, "this is a wrapper around this.Members, don't call it during metadata loading, only call it after the metadata is set to readonly");
                if (null == _properties) 
                {
                    Interlocked.CompareExchange(ref _properties, 
                        new FilteredReadOnlyMetadataCollection( 
                            this.Members, Helper.IsEdmProperty), null);
                } 
                return _properties;
            }
        }
 
        #endregion // Properties
 
        ///  
        /// Returns the Reference type pointing to this entity type
        ///  
        /// 
        public RefType GetReferenceType()
        {
            if (_referenceType == null) 
            {
                Interlocked.CompareExchange(ref _referenceType, new RefType(this), null); 
            } 
            return _referenceType;
        } 

        internal RowType GetKeyRowType(MetadataWorkspace metadataWorkspace)
        {
            if (_keyRow == null) 
            {
                List keyProperties = new List(KeyMembers.Count); 
                foreach (EdmMember keyMember in KeyMembers) 
                {
                    keyProperties.Add(new EdmProperty(keyMember.Name, Helper.GetModelTypeUsage(keyMember))); 
                }
                Interlocked.CompareExchange(ref _keyRow, new RowType(keyProperties), null);
            }
            return _keyRow; 
        }
 
        ///  
        /// Attempts to get the property name for the ----oication between the two given end
        /// names.  Note that this property may not exist if a navigation property is defined 
        /// in one direction but not in the other.
        /// 
        /// the relationship for which a nav property is required
        /// the 'from' end of the association 
        /// the 'to' end of the association
        /// the property name, or null if none was found 
        /// true if a property was found, false otherwise 
        internal bool TryGetNavigationProperty(string relationshipType, string fromName, string toName, out NavigationProperty navigationProperty)
        { 
            // This is a linear search but it's probably okay because the number of entries
            // is generally small and this method is only called to generate code during lighweight
            // code gen.
            foreach (NavigationProperty navProperty in NavigationProperties) 
            {
                if (navProperty.RelationshipType.FullName == relationshipType && 
                    navProperty.FromEndMember.Name == fromName && 
                    navProperty.ToEndMember.Name == toName)
                { 
                    navigationProperty = navProperty;
                    return true;
                }
            } 
            navigationProperty = null;
            return false; 
        } 
    }
 
    internal sealed class ClrEntityType : EntityType
    {
        /// cached CLR type handle, allowing the Type reference to be GC'd
        private readonly System.RuntimeTypeHandle _type; 

        /// cached dynamic method to construct a CLR instance 
        private Delegate _constructor; 

        private readonly string _cspaceTypeName; 

        private readonly string _cspaceNamespaceName;

        private string _hash; 

        ///  
        /// Initializes a new instance of Complex Type with properties from the type. 
        /// 
        /// The CLR type to construct from 
        internal ClrEntityType(Type type, string cspaceNamespaceName, string cspaceTypeName)
            : base(EntityUtil.GenericCheckArgumentNull(type, "type").Name, type.Namespace ?? string.Empty,
            DataSpace.OSpace)
        { 
            System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(cspaceNamespaceName) &&
                !String.IsNullOrEmpty(cspaceTypeName), "Mapping information must never be null"); 
 
            _type = type.TypeHandle;
            _cspaceNamespaceName = cspaceNamespaceName; 
            _cspaceTypeName = cspaceNamespaceName + "." + cspaceTypeName;
            this.Abstract = type.IsAbstract;
        }
 
        /// cached dynamic method to construct a CLR instance
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 
        internal Delegate Constructor 
        {
            get { return _constructor; } 
            set
            {
                // It doesn't matter which delegate wins, but only one should be jitted
                Interlocked.CompareExchange(ref _constructor, value, null); 
            }
        } 
 
        /// 
        ///  
        internal override System.Type ClrType
        {
            get { return Type.GetTypeFromHandle(_type); }
        } 

        internal string CSpaceTypeName { get { return _cspaceTypeName; } } 
 
        internal string CSpaceNamespaceName { get { return _cspaceNamespaceName; } }
 
        /// 
        /// Gets a collision resistent (SHA256) hash of the information used to build
        /// a proxy for this type.  This hash is very, very unlikely to be the same for two
        /// proxies generated from the same CLR type but with different metadata, and is 
        /// guarenteed to be the same for proxies generated from the same metadata.  This
        /// means that when EntityType comparison fails because of metadata eviction, 
        /// the hash can be used to determine whether or not a proxy is of the correct type. 
        /// 
        internal string HashedDescription 
        {
            get
            {
                if (_hash == null) 
                {
                    Interlocked.CompareExchange(ref _hash, BuildEntityTypeHash(), null); 
                } 
                return _hash;
            } 
        }

        /// 
        /// Creates an SHA256 hash of a description of all the metadata relevant to the creation of a proxy type 
        /// for this entity type.
        ///  
        private string BuildEntityTypeHash() 
        {
            var hash = System.Data.Common.Utils.MetadataHelper.CreateSHA256HashAlgorithm() 
                .ComputeHash(Encoding.ASCII.GetBytes(BuildEntityTypeDescription()));

            // convert num bytes to num hex digits
            var builder = new StringBuilder(hash.Length * 2); 
            foreach (byte bite in hash)
            { 
                builder.Append(bite.ToString("X2", CultureInfo.InvariantCulture)); 
            }
 
            return builder.ToString();
        }

        ///  
        /// Creates a description of all the metadata relevant to the creation of a proxy type
        /// for this entity type. 
        ///  
        private string BuildEntityTypeDescription()
        { 
            var builder = new StringBuilder(512);
            Debug.Assert(ClrType != null, "Expecting non-null CLRType of o-space EntityType.");
            builder.Append("CLR:").Append(ClrType.FullName);
            builder.Append("Conceptual:").Append(CSpaceTypeName); 

            var navProps = new SortedSet(); 
            foreach (var navProperty in NavigationProperties) 
            {
                navProps.Add(navProperty.Name + "*" + 
                             navProperty.FromEndMember.Name + "*" +
                             navProperty.FromEndMember.RelationshipMultiplicity + "*" +
                             navProperty.ToEndMember.Name + "*" +
                             navProperty.ToEndMember.RelationshipMultiplicity + "*"); 
            }
            builder.Append("NavProps:"); 
            foreach (var navProp in navProps) 
            {
                builder.Append(navProp); 
            }

            var keys = new SortedSet();
            foreach (var member in KeyMemberNames) 
            {
                keys.Add(member); 
            } 
            builder.Append("Keys:");
            foreach (var key in keys) 
            {
                builder.Append(key + "*");
            }
 
            var scalars = new SortedSet();
            foreach (var member in Members) 
            { 
                if (!keys.Contains(member.Name))
                { 
                    scalars.Add(member.Name + "*");
                }
            }
            builder.Append("Scalars:"); 
            foreach (var scalar in scalars)
            { 
                builder.Append(scalar + "*"); 
            }
 
            return builder.ToString();
        }
    }
} 

// 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