LeafCellTreeNode.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / LeafCellTreeNode.cs / 3 / LeafCellTreeNode.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.Collections.Generic; 
using System.Data.Common.Utils;
using System.Data.Mapping.ViewGeneration.CqlGeneration;
using System.Data.Mapping.ViewGeneration.QueryRewriting;
using System.Linq; 
using System.Text;
using System.Diagnostics; 
using System.Data.Metadata.Edm; 

 
namespace System.Data.Mapping.ViewGeneration.Structures {
    // This class represents the nodes that reside at the leaves of the tree
    internal class LeafCellTreeNode : CellTreeNode {
 
        #region Constructor
        // effects: Encapsulate the cell wrapper in the node 
        internal LeafCellTreeNode(CellNormalizer normalizer, LeftCellWrapper cellWrapper) 
            : base(normalizer)
        { 
            m_cellWrapper = cellWrapper;
            m_leftFragmentQuery = cellWrapper.FragmentQuery;
            cellWrapper.AssertHasUniqueCell();
            m_rightFragmentQuery = FragmentQuery.Create( 
                                        cellWrapper.OriginalCellNumberString,
                                        cellWrapper.CreateRoleBoolean(), 
                                        cellWrapper.RightCellQuery); 
        }
        internal LeafCellTreeNode(CellNormalizer normalizer, LeftCellWrapper cellWrapper, FragmentQuery rightFragmentQuery) 
            : base(normalizer)
        {
            m_cellWrapper = cellWrapper;
            m_leftFragmentQuery = cellWrapper.FragmentQuery; 
            m_rightFragmentQuery = rightFragmentQuery;
        } 
        #endregion 

        #region Fields 
        internal static readonly IEqualityComparer EqualityComparer = new LeafCellTreeNodeComparer();

        // The cell at the leaf level
        private LeftCellWrapper m_cellWrapper; 
        private FragmentQuery m_leftFragmentQuery;
        private FragmentQuery m_rightFragmentQuery; 
        #endregion 

        #region Properties 
        internal LeftCellWrapper LeftCellWrapper {
            get { return m_cellWrapper;}
        }
 
        internal override MemberDomainMap RightDomainMap {
            get { return m_cellWrapper.RightDomainMap; } 
        } 

        // effects: Returns the cell query denoting the right side 
        internal CellQuery RightCellQuery {
            get { return m_cellWrapper.RightCellQuery; }
        }
        // effects: See CellTreeNode.FragmentQuery 
        internal override FragmentQuery LeftFragmentQuery { get { return m_cellWrapper.FragmentQuery; } }
 
        internal override FragmentQuery RightFragmentQuery 
        {
            get 
            {
                Debug.Assert(m_rightFragmentQuery != null, "Unassigned right fragment query");
                return m_rightFragmentQuery;
            } 
        }
 
        // effects: See CellTreeNode.Attributes 
        internal override Set Attributes { get { return m_cellWrapper.Attributes; } }
 
        // effects: See CellTreeNode.Children
        internal override List Children { get { return new List(); } }

        // effects: See CellTreeNode.OpType 
        internal override CellTreeOpType OpType { get { return CellTreeOpType.Leaf; } }
 
        internal override int NumProjectedSlots { 
            get { return RightCellQuery.NumProjectedSlots; }
        } 

        internal override int NumBoolSlots {
            get { return RightCellQuery.NumBoolVars; }
        } 
        #endregion
 
        #region Methods 
        internal override TOutput Accept(CellTreeVisitor visitor, TInput param) {
            return visitor.VisitLeaf(this, param); 
        }

        internal override TOutput Accept(SimpleCellTreeVisitor visitor, TInput param) {
            return visitor.VisitLeaf(this, param); 
        }
 
        internal override bool IsProjectedSlot(int slot) { 
            CellQuery cellQuery = RightCellQuery;
            if (IsBoolSlot(slot)) { 
                return cellQuery.GetBoolVar(SlotToBoolIndex(slot)) != null;
            } else {
                return cellQuery.ProjectedSlotAt(slot) != null;
            } 
        }
        #endregion 
 
        #region Leaf CqlBlock Methods
        internal override CqlBlock ToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, 
            ref List withStatements)
        {
            // Get the projected slots and the boolean expressions
 			int totalSlots = requiredSlots.Length; 
			CellQuery cellQuery = RightCellQuery;
 
            SlotInfo[] projectedSlots = new SlotInfo[totalSlots]; 
            Debug.Assert(cellQuery.NumProjectedSlots + cellQuery.NumBoolVars == totalSlots,
                         "Wrong number of projected slots in node"); 

            Debug.Assert(cellQuery.NumProjectedSlots == ProjectedSlotMap.Count,
                         "Different number of slots in cell query and what we have mappings for");
            // Add the regular fields 
            for (int i = 0; i < cellQuery.NumProjectedSlots; i++) {
                ProjectedSlot slot = cellQuery.ProjectedSlotAt(i); 
                // If the slot is not null, we will project it 
                // For extents, we say that all requiredlots are the only the
                // ones that are CLR non-null. Recall that "real" nulls are 
                // handled by having a CellConstant.Null in ConstantSlot
                if (requiredSlots[i] && slot == null)
                {
                    ConstantSlot defaultValue = new ConstantSlot(CellConstantDomain.GetDefaultValueForMemberPath(ProjectedSlotMap[i], GetLeaves(), CellNormalizer.Config)); 
                    cellQuery.FixMissingSlotAsDefaultConstant(i, defaultValue);
                    slot = defaultValue; 
                } 
                SlotInfo slotInfo = new SlotInfo(requiredSlots[i], slot != null,
                                                 slot, ProjectedSlotMap[i]); 
                projectedSlots[i] = slotInfo;
            }

            // Add the boolean fields 
            for (int boolNum = 0; boolNum < cellQuery.NumBoolVars; boolNum++) {
                BoolExpression expr = cellQuery.GetBoolVar(boolNum); 
                BooleanProjectedSlot boolSlot; 
                if (expr != null) {
                    boolSlot = new BooleanProjectedSlot(expr, identifiers, boolNum); 
                } else {
                    boolSlot = new BooleanProjectedSlot(BoolExpression.False, identifiers, boolNum);
                }
                int slotIndex = BoolIndexToSlot(boolNum); 
                SlotInfo slotInfo = new SlotInfo(requiredSlots[slotIndex], expr != null,
                                                 boolSlot, null); 
                projectedSlots[slotIndex] = slotInfo; 
            }
 
            //See if we are generating a query view and whether there are any colocated foreign keys for which
            //we have to add With statements
            IEnumerable totalProjectedSlots = projectedSlots;
            if ( (cellQuery.Extent.EntityContainer.DataSpace == DataSpace.SSpace) 
                && (this.m_cellWrapper.LeftExtent.BuiltInTypeKind == BuiltInTypeKind.EntitySet))
            { 
                IEnumerable associationSetMaps = 
                    this.CellNormalizer.EntityContainerMapping.GetRelationshipSetMappingsFor(this.m_cellWrapper.LeftExtent, cellQuery.Extent);
                List foreignKeySlots = new List(); 
                foreach (StorageAssociationSetMapping colocatedAssociationSetMap in associationSetMaps)
                {
                    WithStatement withStatement;
                    if (TryGetWithStatement(colocatedAssociationSetMap, this.m_cellWrapper.LeftExtent, cellQuery.JoinTreeRoot, ref foreignKeySlots, out withStatement)) 
                    {
                        withStatements.Add(withStatement); 
                        totalProjectedSlots = projectedSlots.Concat(foreignKeySlots); 
                    }
                } 
            }
            ExtentCqlBlock result = new ExtentCqlBlock(cellQuery.Extent, totalProjectedSlots.ToArray(),
                                                       cellQuery.WhereClause, identifiers, ++blockAliasNum);
            return result; 
        }
 
        private bool TryGetWithStatement(StorageAssociationSetMapping colocatedAssociationSetMap, EntitySetBase thisExtent, JoinTreeNode sRootNode, 
            ref List foreignKeySlots, out WithStatement withStatement)
        { 
            Debug.Assert(foreignKeySlots != null);
            withStatement = null;

            //Get the map for foreign key end 
            StorageEndPropertyMapping foreignKeyEndMap = GetForeignKeyEndMapFromAssocitionMap(colocatedAssociationSetMap, thisExtent);
            if ( (foreignKeyEndMap == null) 
                || (foreignKeyEndMap.EndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) ) 
            {
                return false; 
            }

            //Collect the member paths for edm scalar properties that are part of the end mapping
            //These will be used as part of With Statement 
            List associationEndMemberPaths = new List();
            //Get the member path for AssociationSet 
            AssociationSet associationSet = (AssociationSet)colocatedAssociationSetMap.Set; 
            MemberPath prefix = new MemberPath(associationSet, foreignKeyEndMap.EndMember, this.CellNormalizer.Workspace);
            //Get the key properties from edm type since the query parser depends on the order of key members 
            EntityTypeBase edmEntityType = ((RefType)(foreignKeyEndMap.EndMember.TypeUsage.EdmType)).ElementType;
            IEnumerable propertyMaps = foreignKeyEndMap.Properties.Cast();
            foreach (EdmProperty edmProperty in  edmEntityType.KeyMembers)
            { 
                IEnumerable scalarPropertyMaps = propertyMaps.Where(propMap => (propMap.EdmProperty.Equals(edmProperty)));
                Debug.Assert(scalarPropertyMaps.Count() == 1, "Can't Map the same column multiple times in the same end"); 
                StorageScalarPropertyMapping scalarPropertyMap = scalarPropertyMaps.First(); 
                //Create SlotInfo for Freign Key member that needs to be projected
                JoinTreeSlot sSlot = new JoinTreeSlot(sRootNode.CreateAttributeNode(scalarPropertyMap.ColumnProperty)); 
                MemberPath endMemberKeyPath = new MemberPath(prefix, edmProperty);
                associationEndMemberPaths.Add(endMemberKeyPath);
                foreignKeySlots.Add(new SlotInfo(true, true, sSlot, endMemberKeyPath));
            } 
            //Now create the With Statement with all the needed info like ToEntitySet, AssociationSet, FromRoleName, ToRoleName
            EntitySet refEntitySet = MetadataHelper.GetEntitySetAtEnd(associationSet, (AssociationEndMember)(foreignKeyEndMap.EndMember)); 
            AssociationEndMember fromEnd = MetadataHelper.GetOtherAssociationEnd((AssociationEndMember)(foreignKeyEndMap.EndMember)); 
            EntityType endEntityType = (EntityType)(((RefType)foreignKeyEndMap.EndMember.TypeUsage.EdmType).ElementType);
            EntityType fromEndEntityType = (EntityType)(((RefType)fromEnd.TypeUsage.EdmType).ElementType); 
            withStatement = new WithStatement(refEntitySet, endEntityType, fromEndEntityType,associationSet, fromEnd.Name, foreignKeyEndMap.EndMember.Name, associationEndMemberPaths);
            return true;
        }
 
        //Gets the end that is not mapped to the primary key of the table
        private StorageEndPropertyMapping GetForeignKeyEndMapFromAssocitionMap(StorageAssociationSetMapping colocatedAssociationSetMap, EntitySetBase thisExtent) 
        { 
            StorageMappingFragment mapFragment = colocatedAssociationSetMap.TypeMappings.First().MappingFragments.First();
            EntitySet storeEntitySet = (EntitySet)(colocatedAssociationSetMap.StoreEntitySet); 
            IEnumerable keyProperties = storeEntitySet.ElementType.KeyMembers;
            //Find the end that's mapped to primary key
            foreach (StorageEndPropertyMapping endMap in mapFragment.Properties)
            { 
                IEnumerable endStoreMembers = endMap.StoreProperties;
                if (endStoreMembers.SequenceEqual(keyProperties, EqualityComparer.Default)) 
                { 
                    //Return the map for the other end since that is the foreign key end
                    IEnumerable otherEnds = mapFragment.Properties.OfType().Where(eMap => (!eMap.Equals(endMap))); 
                    Debug.Assert(otherEnds.Count() == 1);
                    return otherEnds.First();
                }
            } 
            //This is probably defensive, but there should be no problem in falling back on the
            //AssociationSetMap if colocated foreign key is not found for some reason. 
            return null; 
        }
        #endregion 

        #region String Methods
        // effects: See CellTreeNode.ToString
        internal override void ToCompactString(StringBuilder stringBuilder) { 
            m_cellWrapper.ToCompactString(stringBuilder);
        } 
 
        #endregion
 
        #region IEqualityComparer
        // A comparer that equates leaf nodes if the wrapper is the same
        private class LeafCellTreeNodeComparer : IEqualityComparer {
 
            public bool Equals(LeafCellTreeNode left, LeafCellTreeNode right) {
                // Quick check with references 
                if (object.ReferenceEquals(left, right)) { 
                    // Gets the Null and Undefined case as well
                    return true; 
                }
                // One of them is non-null at least
                if (left == null || right == null) {
                    return false; 
                }
                // Both are non-null at this point 
                return left.m_cellWrapper.Equals(right.m_cellWrapper); 
            }
 
            public int GetHashCode(LeafCellTreeNode node) {
                return node.m_cellWrapper.GetHashCode();
            }
        } 
        #endregion
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.Collections.Generic; 
using System.Data.Common.Utils;
using System.Data.Mapping.ViewGeneration.CqlGeneration;
using System.Data.Mapping.ViewGeneration.QueryRewriting;
using System.Linq; 
using System.Text;
using System.Diagnostics; 
using System.Data.Metadata.Edm; 

 
namespace System.Data.Mapping.ViewGeneration.Structures {
    // This class represents the nodes that reside at the leaves of the tree
    internal class LeafCellTreeNode : CellTreeNode {
 
        #region Constructor
        // effects: Encapsulate the cell wrapper in the node 
        internal LeafCellTreeNode(CellNormalizer normalizer, LeftCellWrapper cellWrapper) 
            : base(normalizer)
        { 
            m_cellWrapper = cellWrapper;
            m_leftFragmentQuery = cellWrapper.FragmentQuery;
            cellWrapper.AssertHasUniqueCell();
            m_rightFragmentQuery = FragmentQuery.Create( 
                                        cellWrapper.OriginalCellNumberString,
                                        cellWrapper.CreateRoleBoolean(), 
                                        cellWrapper.RightCellQuery); 
        }
        internal LeafCellTreeNode(CellNormalizer normalizer, LeftCellWrapper cellWrapper, FragmentQuery rightFragmentQuery) 
            : base(normalizer)
        {
            m_cellWrapper = cellWrapper;
            m_leftFragmentQuery = cellWrapper.FragmentQuery; 
            m_rightFragmentQuery = rightFragmentQuery;
        } 
        #endregion 

        #region Fields 
        internal static readonly IEqualityComparer EqualityComparer = new LeafCellTreeNodeComparer();

        // The cell at the leaf level
        private LeftCellWrapper m_cellWrapper; 
        private FragmentQuery m_leftFragmentQuery;
        private FragmentQuery m_rightFragmentQuery; 
        #endregion 

        #region Properties 
        internal LeftCellWrapper LeftCellWrapper {
            get { return m_cellWrapper;}
        }
 
        internal override MemberDomainMap RightDomainMap {
            get { return m_cellWrapper.RightDomainMap; } 
        } 

        // effects: Returns the cell query denoting the right side 
        internal CellQuery RightCellQuery {
            get { return m_cellWrapper.RightCellQuery; }
        }
        // effects: See CellTreeNode.FragmentQuery 
        internal override FragmentQuery LeftFragmentQuery { get { return m_cellWrapper.FragmentQuery; } }
 
        internal override FragmentQuery RightFragmentQuery 
        {
            get 
            {
                Debug.Assert(m_rightFragmentQuery != null, "Unassigned right fragment query");
                return m_rightFragmentQuery;
            } 
        }
 
        // effects: See CellTreeNode.Attributes 
        internal override Set Attributes { get { return m_cellWrapper.Attributes; } }
 
        // effects: See CellTreeNode.Children
        internal override List Children { get { return new List(); } }

        // effects: See CellTreeNode.OpType 
        internal override CellTreeOpType OpType { get { return CellTreeOpType.Leaf; } }
 
        internal override int NumProjectedSlots { 
            get { return RightCellQuery.NumProjectedSlots; }
        } 

        internal override int NumBoolSlots {
            get { return RightCellQuery.NumBoolVars; }
        } 
        #endregion
 
        #region Methods 
        internal override TOutput Accept(CellTreeVisitor visitor, TInput param) {
            return visitor.VisitLeaf(this, param); 
        }

        internal override TOutput Accept(SimpleCellTreeVisitor visitor, TInput param) {
            return visitor.VisitLeaf(this, param); 
        }
 
        internal override bool IsProjectedSlot(int slot) { 
            CellQuery cellQuery = RightCellQuery;
            if (IsBoolSlot(slot)) { 
                return cellQuery.GetBoolVar(SlotToBoolIndex(slot)) != null;
            } else {
                return cellQuery.ProjectedSlotAt(slot) != null;
            } 
        }
        #endregion 
 
        #region Leaf CqlBlock Methods
        internal override CqlBlock ToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, 
            ref List withStatements)
        {
            // Get the projected slots and the boolean expressions
 			int totalSlots = requiredSlots.Length; 
			CellQuery cellQuery = RightCellQuery;
 
            SlotInfo[] projectedSlots = new SlotInfo[totalSlots]; 
            Debug.Assert(cellQuery.NumProjectedSlots + cellQuery.NumBoolVars == totalSlots,
                         "Wrong number of projected slots in node"); 

            Debug.Assert(cellQuery.NumProjectedSlots == ProjectedSlotMap.Count,
                         "Different number of slots in cell query and what we have mappings for");
            // Add the regular fields 
            for (int i = 0; i < cellQuery.NumProjectedSlots; i++) {
                ProjectedSlot slot = cellQuery.ProjectedSlotAt(i); 
                // If the slot is not null, we will project it 
                // For extents, we say that all requiredlots are the only the
                // ones that are CLR non-null. Recall that "real" nulls are 
                // handled by having a CellConstant.Null in ConstantSlot
                if (requiredSlots[i] && slot == null)
                {
                    ConstantSlot defaultValue = new ConstantSlot(CellConstantDomain.GetDefaultValueForMemberPath(ProjectedSlotMap[i], GetLeaves(), CellNormalizer.Config)); 
                    cellQuery.FixMissingSlotAsDefaultConstant(i, defaultValue);
                    slot = defaultValue; 
                } 
                SlotInfo slotInfo = new SlotInfo(requiredSlots[i], slot != null,
                                                 slot, ProjectedSlotMap[i]); 
                projectedSlots[i] = slotInfo;
            }

            // Add the boolean fields 
            for (int boolNum = 0; boolNum < cellQuery.NumBoolVars; boolNum++) {
                BoolExpression expr = cellQuery.GetBoolVar(boolNum); 
                BooleanProjectedSlot boolSlot; 
                if (expr != null) {
                    boolSlot = new BooleanProjectedSlot(expr, identifiers, boolNum); 
                } else {
                    boolSlot = new BooleanProjectedSlot(BoolExpression.False, identifiers, boolNum);
                }
                int slotIndex = BoolIndexToSlot(boolNum); 
                SlotInfo slotInfo = new SlotInfo(requiredSlots[slotIndex], expr != null,
                                                 boolSlot, null); 
                projectedSlots[slotIndex] = slotInfo; 
            }
 
            //See if we are generating a query view and whether there are any colocated foreign keys for which
            //we have to add With statements
            IEnumerable totalProjectedSlots = projectedSlots;
            if ( (cellQuery.Extent.EntityContainer.DataSpace == DataSpace.SSpace) 
                && (this.m_cellWrapper.LeftExtent.BuiltInTypeKind == BuiltInTypeKind.EntitySet))
            { 
                IEnumerable associationSetMaps = 
                    this.CellNormalizer.EntityContainerMapping.GetRelationshipSetMappingsFor(this.m_cellWrapper.LeftExtent, cellQuery.Extent);
                List foreignKeySlots = new List(); 
                foreach (StorageAssociationSetMapping colocatedAssociationSetMap in associationSetMaps)
                {
                    WithStatement withStatement;
                    if (TryGetWithStatement(colocatedAssociationSetMap, this.m_cellWrapper.LeftExtent, cellQuery.JoinTreeRoot, ref foreignKeySlots, out withStatement)) 
                    {
                        withStatements.Add(withStatement); 
                        totalProjectedSlots = projectedSlots.Concat(foreignKeySlots); 
                    }
                } 
            }
            ExtentCqlBlock result = new ExtentCqlBlock(cellQuery.Extent, totalProjectedSlots.ToArray(),
                                                       cellQuery.WhereClause, identifiers, ++blockAliasNum);
            return result; 
        }
 
        private bool TryGetWithStatement(StorageAssociationSetMapping colocatedAssociationSetMap, EntitySetBase thisExtent, JoinTreeNode sRootNode, 
            ref List foreignKeySlots, out WithStatement withStatement)
        { 
            Debug.Assert(foreignKeySlots != null);
            withStatement = null;

            //Get the map for foreign key end 
            StorageEndPropertyMapping foreignKeyEndMap = GetForeignKeyEndMapFromAssocitionMap(colocatedAssociationSetMap, thisExtent);
            if ( (foreignKeyEndMap == null) 
                || (foreignKeyEndMap.EndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) ) 
            {
                return false; 
            }

            //Collect the member paths for edm scalar properties that are part of the end mapping
            //These will be used as part of With Statement 
            List associationEndMemberPaths = new List();
            //Get the member path for AssociationSet 
            AssociationSet associationSet = (AssociationSet)colocatedAssociationSetMap.Set; 
            MemberPath prefix = new MemberPath(associationSet, foreignKeyEndMap.EndMember, this.CellNormalizer.Workspace);
            //Get the key properties from edm type since the query parser depends on the order of key members 
            EntityTypeBase edmEntityType = ((RefType)(foreignKeyEndMap.EndMember.TypeUsage.EdmType)).ElementType;
            IEnumerable propertyMaps = foreignKeyEndMap.Properties.Cast();
            foreach (EdmProperty edmProperty in  edmEntityType.KeyMembers)
            { 
                IEnumerable scalarPropertyMaps = propertyMaps.Where(propMap => (propMap.EdmProperty.Equals(edmProperty)));
                Debug.Assert(scalarPropertyMaps.Count() == 1, "Can't Map the same column multiple times in the same end"); 
                StorageScalarPropertyMapping scalarPropertyMap = scalarPropertyMaps.First(); 
                //Create SlotInfo for Freign Key member that needs to be projected
                JoinTreeSlot sSlot = new JoinTreeSlot(sRootNode.CreateAttributeNode(scalarPropertyMap.ColumnProperty)); 
                MemberPath endMemberKeyPath = new MemberPath(prefix, edmProperty);
                associationEndMemberPaths.Add(endMemberKeyPath);
                foreignKeySlots.Add(new SlotInfo(true, true, sSlot, endMemberKeyPath));
            } 
            //Now create the With Statement with all the needed info like ToEntitySet, AssociationSet, FromRoleName, ToRoleName
            EntitySet refEntitySet = MetadataHelper.GetEntitySetAtEnd(associationSet, (AssociationEndMember)(foreignKeyEndMap.EndMember)); 
            AssociationEndMember fromEnd = MetadataHelper.GetOtherAssociationEnd((AssociationEndMember)(foreignKeyEndMap.EndMember)); 
            EntityType endEntityType = (EntityType)(((RefType)foreignKeyEndMap.EndMember.TypeUsage.EdmType).ElementType);
            EntityType fromEndEntityType = (EntityType)(((RefType)fromEnd.TypeUsage.EdmType).ElementType); 
            withStatement = new WithStatement(refEntitySet, endEntityType, fromEndEntityType,associationSet, fromEnd.Name, foreignKeyEndMap.EndMember.Name, associationEndMemberPaths);
            return true;
        }
 
        //Gets the end that is not mapped to the primary key of the table
        private StorageEndPropertyMapping GetForeignKeyEndMapFromAssocitionMap(StorageAssociationSetMapping colocatedAssociationSetMap, EntitySetBase thisExtent) 
        { 
            StorageMappingFragment mapFragment = colocatedAssociationSetMap.TypeMappings.First().MappingFragments.First();
            EntitySet storeEntitySet = (EntitySet)(colocatedAssociationSetMap.StoreEntitySet); 
            IEnumerable keyProperties = storeEntitySet.ElementType.KeyMembers;
            //Find the end that's mapped to primary key
            foreach (StorageEndPropertyMapping endMap in mapFragment.Properties)
            { 
                IEnumerable endStoreMembers = endMap.StoreProperties;
                if (endStoreMembers.SequenceEqual(keyProperties, EqualityComparer.Default)) 
                { 
                    //Return the map for the other end since that is the foreign key end
                    IEnumerable otherEnds = mapFragment.Properties.OfType().Where(eMap => (!eMap.Equals(endMap))); 
                    Debug.Assert(otherEnds.Count() == 1);
                    return otherEnds.First();
                }
            } 
            //This is probably defensive, but there should be no problem in falling back on the
            //AssociationSetMap if colocated foreign key is not found for some reason. 
            return null; 
        }
        #endregion 

        #region String Methods
        // effects: See CellTreeNode.ToString
        internal override void ToCompactString(StringBuilder stringBuilder) { 
            m_cellWrapper.ToCompactString(stringBuilder);
        } 
 
        #endregion
 
        #region IEqualityComparer
        // A comparer that equates leaf nodes if the wrapper is the same
        private class LeafCellTreeNodeComparer : IEqualityComparer {
 
            public bool Equals(LeafCellTreeNode left, LeafCellTreeNode right) {
                // Quick check with references 
                if (object.ReferenceEquals(left, right)) { 
                    // Gets the Null and Undefined case as well
                    return true; 
                }
                // One of them is non-null at least
                if (left == null || right == null) {
                    return false; 
                }
                // Both are non-null at this point 
                return left.m_cellWrapper.Equals(right.m_cellWrapper); 
            }
 
            public int GetHashCode(LeafCellTreeNode node) {
                return node.m_cellWrapper.GetHashCode();
            }
        } 
        #endregion
    } 
} 

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