FragmentQueryKB.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 / DataEntity / System / Data / Map / ViewGeneration / QueryRewriting / FragmentQueryKB.cs / 1305376 / FragmentQueryKB.cs

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

using System; 
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Data.Common.Utils; 
using System.Data.Common.Utils.Boolean;
using System.Data.Mapping.ViewGeneration.Structures; 
using System.Data.Metadata.Edm; 
using System.Linq;
 
namespace System.Data.Mapping.ViewGeneration.QueryRewriting
{
    internal class FragmentQueryKB : KnowledgeBase>
    { 
        private BoolExpr> _kbExpression = TrueExpr>.Value;
 
        internal override void AddFact(BoolExpr> fact) 
        {
            base.AddFact(fact); 
            _kbExpression = new AndExpr>(_kbExpression, fact);
        }
        internal BoolExpr> KbExpression
        { 
            get { return _kbExpression; }
        } 
 
        internal void CreateVariableConstraints(EntitySetBase extent, MemberDomainMap domainMap, EdmItemCollection edmItemCollection)
        { 
            CreateVariableConstraintsRecursion(extent.ElementType, new MemberPath(extent), domainMap, edmItemCollection);
        }

        internal void CreateAssociationConstraints(EntitySetBase extent, MemberDomainMap domainMap, EdmItemCollection edmItemCollection) 
        {
            AssociationSet assocSet = extent as AssociationSet; 
            if (assocSet != null) 
            {
                BoolExpression assocSetExpr = BoolExpression.CreateLiteral(new RoleBoolean(assocSet), domainMap); 

                //Set of Keys for this Association Set
                //need to key on EdmMember and EdmType because A, B subtype of C, can have the same id (EdmMember) that is defined in C.
                HashSet> associationkeys = new HashSet>(); 

 
                //foreach end, add each Key 
                foreach (var endMember in assocSet.ElementType.AssociationEndMembers)
                { 
                    EntityType type = (EntityType)((RefType)endMember.TypeUsage.EdmType).ElementType;
                    type.KeyMembers.All(member => associationkeys.Add(new Pair(member, type)) || true /* prevent early termination */);
                }
 
                foreach (AssociationSetEnd end in assocSet.AssociationSetEnds)
                { 
                    // construct type condition 
                    HashSet derivedTypes = new HashSet();
                    derivedTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(end.CorrespondingAssociationEndMember.TypeUsage.EdmType, edmItemCollection, false)); 

                    BoolExpression typeCondition = CreateIsOfTypeCondition(new MemberPath(end.EntitySet),
                                                        derivedTypes, domainMap);
 
                    BoolExpression inRoleExpression = BoolExpression.CreateLiteral(new RoleBoolean(end), domainMap);
                    BoolExpression inSetExpression = BoolExpression.CreateAnd( 
                                  BoolExpression.CreateLiteral(new RoleBoolean(end.EntitySet), domainMap), 
                                  typeCondition);
 
                    // InRole -> (InSet AND type(Set)=T)
                    AddImplication(inRoleExpression.Tree, inSetExpression.Tree);

                    if (MetadataHelper.IsEveryOtherEndAtLeastOne(assocSet, end.CorrespondingAssociationEndMember)) 
                    {
                        AddImplication(inSetExpression.Tree, inRoleExpression.Tree); 
                    } 

                    // Add equivalence between association set an End/Role if necessary. 
                    //   Equivalence is added when a given association end's keys subsumes keys for
                    //   all the other association end.

                    // For example: We have Entity Sets A[id1], B[id2, id3] and an association A_B between them. 
                    // Ref Constraint A.id1 = B.id2
                    // In this case, the Association Set has Key  
                    // id1 alone can not identify a unique tuple in the Association Set, but  can. 
                    // Therefore we add a constraint: InSet(B) <=> InEnd(A_B.B)
 
                    if (MetadataHelper.DoesEndKeySubsumeAssociationSetKey(assocSet,
                        end.CorrespondingAssociationEndMember,
                        associationkeys))
                    { 
                        AddEquivalence(inRoleExpression.Tree, assocSetExpr.Tree);
                    } 
 
                }
 
                // add rules for referential constraints (borrowed from LeftCellWrapper.cs)
                AssociationType assocType = assocSet.ElementType;

                foreach (ReferentialConstraint constraint in assocType.ReferentialConstraints) 
                {
                    AssociationEndMember toEndMember = (AssociationEndMember)constraint.ToRole; 
                    EntitySet toEntitySet = MetadataHelper.GetEntitySetAtEnd(assocSet, toEndMember); 
                    // Check if the keys of the entitySet's are equal to what is specified in the constraint
                    // How annoying that KeyMembers returns EdmMember and not EdmProperty 
                    IEnumerable toProperties = Helpers.AsSuperTypeList(constraint.ToProperties);
                    if (Helpers.IsSetEqual(toProperties, toEntitySet.ElementType.KeyMembers, EqualityComparer.Default))
                    {
                        // Now check that the FromEnd is 1..1 (only then will all the Addresses be present in the assoc set) 
                        if (constraint.FromRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One))
                        { 
                            // Make sure that the ToEnd is not 0..* because then the schema is broken 
                            Debug.Assert(constraint.ToRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.Many) == false);
                            // Equate the ends 
                            BoolExpression inRoleExpression1 = BoolExpression.CreateLiteral(new RoleBoolean(assocSet.AssociationSetEnds[0]), domainMap);
                            BoolExpression inRoleExpression2 = BoolExpression.CreateLiteral(new RoleBoolean(assocSet.AssociationSetEnds[1]), domainMap);
                            AddEquivalence(inRoleExpression1.Tree, inRoleExpression2.Tree);
                        } 
                    }
                } 
            } 
        }
 
        internal void CreateEquivalenceConstraintForOneToOneForeignKeyAssociation(AssociationSet assocSet, MemberDomainMap domainMap,
            EdmItemCollection edmItemCollection)
        {
            AssociationType assocType = assocSet.ElementType; 
            foreach (ReferentialConstraint constraint in assocType.ReferentialConstraints)
            { 
                AssociationEndMember toEndMember = (AssociationEndMember)constraint.ToRole; 
                AssociationEndMember fromEndMember = (AssociationEndMember)constraint.FromRole;
                EntitySet toEntitySet = MetadataHelper.GetEntitySetAtEnd(assocSet, toEndMember); 
                EntitySet fromEntitySet = MetadataHelper.GetEntitySetAtEnd(assocSet, fromEndMember);

                // Check if the keys of the entitySet's are equal to what is specified in the constraint
                IEnumerable toProperties = Helpers.AsSuperTypeList(constraint.ToProperties); 
                if (Helpers.IsSetEqual(toProperties, toEntitySet.ElementType.KeyMembers, EqualityComparer.Default))
                { 
                    //make sure that the method called with a 1:1 association 
                    Debug.Assert(constraint.FromRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One));
                    Debug.Assert(constraint.ToRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One)); 
                    // Create an Equivalence between the two Sets participating in this AssociationSet
                    BoolExpression fromSetExpression = BoolExpression.CreateLiteral(new RoleBoolean(fromEntitySet), domainMap);
                    BoolExpression toSetExpression = BoolExpression.CreateLiteral(new RoleBoolean(toEntitySet), domainMap);
                    AddEquivalence(fromSetExpression.Tree, toSetExpression.Tree); 
                }
            } 
        } 

        private void CreateVariableConstraintsRecursion(EdmType edmType, MemberPath currentPath, MemberDomainMap domainMap, EdmItemCollection edmItemCollection) 
        {
            // Add the types can member have, i.e., its type and its subtypes
            HashSet possibleTypes = new HashSet();
            possibleTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(edmType, edmItemCollection, true)); 

            foreach (EdmType possibleType in possibleTypes) 
            { 
                // determine type domain
 
                HashSet derivedTypes = new HashSet();
                derivedTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(possibleType, edmItemCollection, false));
                if (derivedTypes.Count != 0)
                { 
                    BoolExpression typeCondition = CreateIsOfTypeCondition(currentPath, derivedTypes, domainMap);
                    BoolExpression typeConditionComplement = BoolExpression.CreateNot(typeCondition); 
                    if (false == typeConditionComplement.IsSatisfiable()) 
                    {
                        continue; 
                    }

                    StructuralType structuralType = (StructuralType)possibleType;
                    foreach (EdmProperty childProperty in structuralType.GetDeclaredOnlyMembers()) 
                    {
                        MemberPath childPath = new MemberPath(currentPath, childProperty); 
                        bool isScalar = MetadataHelper.IsNonRefSimpleMember(childProperty); 

                        if (domainMap.IsConditionMember(childPath) || domainMap.IsProjectedConditionMember(childPath)) 
                        {
                            BoolExpression nullCondition;
                            List childDomain = new List(domainMap.GetDomain(childPath));
                            if (isScalar) 
                            {
                                nullCondition = BoolExpression.CreateLiteral(new ScalarRestriction(new MemberProjectedSlot(childPath), 
                                                                             new Domain(ScalarConstant.Undefined, childDomain)), domainMap); 
                            }
                            else 
                            {
                                nullCondition = BoolExpression.CreateLiteral(new TypeRestriction(new MemberProjectedSlot(childPath),
                                                                             new Domain(TypeConstant.Undefined, childDomain)), domainMap);
                            } 
                            // Properties not occuring in type are UNDEFINED
                            AddEquivalence(typeConditionComplement.Tree, nullCondition.Tree); 
                        } 

                        // recurse into complex types 
                        if (false == isScalar)
                        {
                            CreateVariableConstraintsRecursion(childPath.EdmType, childPath, domainMap, edmItemCollection);
                        } 
                    }
                } 
            } 
        }
 
        private static BoolExpression CreateIsOfTypeCondition(MemberPath currentPath, IEnumerable derivedTypes, MemberDomainMap domainMap)
        {
            Domain typeDomain = new Domain(derivedTypes.Select(derivedType => (Constant)new TypeConstant(derivedType)), domainMap.GetDomain(currentPath));
            BoolExpression typeCondition = BoolExpression.CreateLiteral(new TypeRestriction(new MemberProjectedSlot(currentPath), typeDomain), domainMap); 
            return typeCondition;
        } 
    } 
}

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

using System; 
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Data.Common.Utils; 
using System.Data.Common.Utils.Boolean;
using System.Data.Mapping.ViewGeneration.Structures; 
using System.Data.Metadata.Edm; 
using System.Linq;
 
namespace System.Data.Mapping.ViewGeneration.QueryRewriting
{
    internal class FragmentQueryKB : KnowledgeBase>
    { 
        private BoolExpr> _kbExpression = TrueExpr>.Value;
 
        internal override void AddFact(BoolExpr> fact) 
        {
            base.AddFact(fact); 
            _kbExpression = new AndExpr>(_kbExpression, fact);
        }
        internal BoolExpr> KbExpression
        { 
            get { return _kbExpression; }
        } 
 
        internal void CreateVariableConstraints(EntitySetBase extent, MemberDomainMap domainMap, EdmItemCollection edmItemCollection)
        { 
            CreateVariableConstraintsRecursion(extent.ElementType, new MemberPath(extent), domainMap, edmItemCollection);
        }

        internal void CreateAssociationConstraints(EntitySetBase extent, MemberDomainMap domainMap, EdmItemCollection edmItemCollection) 
        {
            AssociationSet assocSet = extent as AssociationSet; 
            if (assocSet != null) 
            {
                BoolExpression assocSetExpr = BoolExpression.CreateLiteral(new RoleBoolean(assocSet), domainMap); 

                //Set of Keys for this Association Set
                //need to key on EdmMember and EdmType because A, B subtype of C, can have the same id (EdmMember) that is defined in C.
                HashSet> associationkeys = new HashSet>(); 

 
                //foreach end, add each Key 
                foreach (var endMember in assocSet.ElementType.AssociationEndMembers)
                { 
                    EntityType type = (EntityType)((RefType)endMember.TypeUsage.EdmType).ElementType;
                    type.KeyMembers.All(member => associationkeys.Add(new Pair(member, type)) || true /* prevent early termination */);
                }
 
                foreach (AssociationSetEnd end in assocSet.AssociationSetEnds)
                { 
                    // construct type condition 
                    HashSet derivedTypes = new HashSet();
                    derivedTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(end.CorrespondingAssociationEndMember.TypeUsage.EdmType, edmItemCollection, false)); 

                    BoolExpression typeCondition = CreateIsOfTypeCondition(new MemberPath(end.EntitySet),
                                                        derivedTypes, domainMap);
 
                    BoolExpression inRoleExpression = BoolExpression.CreateLiteral(new RoleBoolean(end), domainMap);
                    BoolExpression inSetExpression = BoolExpression.CreateAnd( 
                                  BoolExpression.CreateLiteral(new RoleBoolean(end.EntitySet), domainMap), 
                                  typeCondition);
 
                    // InRole -> (InSet AND type(Set)=T)
                    AddImplication(inRoleExpression.Tree, inSetExpression.Tree);

                    if (MetadataHelper.IsEveryOtherEndAtLeastOne(assocSet, end.CorrespondingAssociationEndMember)) 
                    {
                        AddImplication(inSetExpression.Tree, inRoleExpression.Tree); 
                    } 

                    // Add equivalence between association set an End/Role if necessary. 
                    //   Equivalence is added when a given association end's keys subsumes keys for
                    //   all the other association end.

                    // For example: We have Entity Sets A[id1], B[id2, id3] and an association A_B between them. 
                    // Ref Constraint A.id1 = B.id2
                    // In this case, the Association Set has Key  
                    // id1 alone can not identify a unique tuple in the Association Set, but  can. 
                    // Therefore we add a constraint: InSet(B) <=> InEnd(A_B.B)
 
                    if (MetadataHelper.DoesEndKeySubsumeAssociationSetKey(assocSet,
                        end.CorrespondingAssociationEndMember,
                        associationkeys))
                    { 
                        AddEquivalence(inRoleExpression.Tree, assocSetExpr.Tree);
                    } 
 
                }
 
                // add rules for referential constraints (borrowed from LeftCellWrapper.cs)
                AssociationType assocType = assocSet.ElementType;

                foreach (ReferentialConstraint constraint in assocType.ReferentialConstraints) 
                {
                    AssociationEndMember toEndMember = (AssociationEndMember)constraint.ToRole; 
                    EntitySet toEntitySet = MetadataHelper.GetEntitySetAtEnd(assocSet, toEndMember); 
                    // Check if the keys of the entitySet's are equal to what is specified in the constraint
                    // How annoying that KeyMembers returns EdmMember and not EdmProperty 
                    IEnumerable toProperties = Helpers.AsSuperTypeList(constraint.ToProperties);
                    if (Helpers.IsSetEqual(toProperties, toEntitySet.ElementType.KeyMembers, EqualityComparer.Default))
                    {
                        // Now check that the FromEnd is 1..1 (only then will all the Addresses be present in the assoc set) 
                        if (constraint.FromRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One))
                        { 
                            // Make sure that the ToEnd is not 0..* because then the schema is broken 
                            Debug.Assert(constraint.ToRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.Many) == false);
                            // Equate the ends 
                            BoolExpression inRoleExpression1 = BoolExpression.CreateLiteral(new RoleBoolean(assocSet.AssociationSetEnds[0]), domainMap);
                            BoolExpression inRoleExpression2 = BoolExpression.CreateLiteral(new RoleBoolean(assocSet.AssociationSetEnds[1]), domainMap);
                            AddEquivalence(inRoleExpression1.Tree, inRoleExpression2.Tree);
                        } 
                    }
                } 
            } 
        }
 
        internal void CreateEquivalenceConstraintForOneToOneForeignKeyAssociation(AssociationSet assocSet, MemberDomainMap domainMap,
            EdmItemCollection edmItemCollection)
        {
            AssociationType assocType = assocSet.ElementType; 
            foreach (ReferentialConstraint constraint in assocType.ReferentialConstraints)
            { 
                AssociationEndMember toEndMember = (AssociationEndMember)constraint.ToRole; 
                AssociationEndMember fromEndMember = (AssociationEndMember)constraint.FromRole;
                EntitySet toEntitySet = MetadataHelper.GetEntitySetAtEnd(assocSet, toEndMember); 
                EntitySet fromEntitySet = MetadataHelper.GetEntitySetAtEnd(assocSet, fromEndMember);

                // Check if the keys of the entitySet's are equal to what is specified in the constraint
                IEnumerable toProperties = Helpers.AsSuperTypeList(constraint.ToProperties); 
                if (Helpers.IsSetEqual(toProperties, toEntitySet.ElementType.KeyMembers, EqualityComparer.Default))
                { 
                    //make sure that the method called with a 1:1 association 
                    Debug.Assert(constraint.FromRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One));
                    Debug.Assert(constraint.ToRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One)); 
                    // Create an Equivalence between the two Sets participating in this AssociationSet
                    BoolExpression fromSetExpression = BoolExpression.CreateLiteral(new RoleBoolean(fromEntitySet), domainMap);
                    BoolExpression toSetExpression = BoolExpression.CreateLiteral(new RoleBoolean(toEntitySet), domainMap);
                    AddEquivalence(fromSetExpression.Tree, toSetExpression.Tree); 
                }
            } 
        } 

        private void CreateVariableConstraintsRecursion(EdmType edmType, MemberPath currentPath, MemberDomainMap domainMap, EdmItemCollection edmItemCollection) 
        {
            // Add the types can member have, i.e., its type and its subtypes
            HashSet possibleTypes = new HashSet();
            possibleTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(edmType, edmItemCollection, true)); 

            foreach (EdmType possibleType in possibleTypes) 
            { 
                // determine type domain
 
                HashSet derivedTypes = new HashSet();
                derivedTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(possibleType, edmItemCollection, false));
                if (derivedTypes.Count != 0)
                { 
                    BoolExpression typeCondition = CreateIsOfTypeCondition(currentPath, derivedTypes, domainMap);
                    BoolExpression typeConditionComplement = BoolExpression.CreateNot(typeCondition); 
                    if (false == typeConditionComplement.IsSatisfiable()) 
                    {
                        continue; 
                    }

                    StructuralType structuralType = (StructuralType)possibleType;
                    foreach (EdmProperty childProperty in structuralType.GetDeclaredOnlyMembers()) 
                    {
                        MemberPath childPath = new MemberPath(currentPath, childProperty); 
                        bool isScalar = MetadataHelper.IsNonRefSimpleMember(childProperty); 

                        if (domainMap.IsConditionMember(childPath) || domainMap.IsProjectedConditionMember(childPath)) 
                        {
                            BoolExpression nullCondition;
                            List childDomain = new List(domainMap.GetDomain(childPath));
                            if (isScalar) 
                            {
                                nullCondition = BoolExpression.CreateLiteral(new ScalarRestriction(new MemberProjectedSlot(childPath), 
                                                                             new Domain(ScalarConstant.Undefined, childDomain)), domainMap); 
                            }
                            else 
                            {
                                nullCondition = BoolExpression.CreateLiteral(new TypeRestriction(new MemberProjectedSlot(childPath),
                                                                             new Domain(TypeConstant.Undefined, childDomain)), domainMap);
                            } 
                            // Properties not occuring in type are UNDEFINED
                            AddEquivalence(typeConditionComplement.Tree, nullCondition.Tree); 
                        } 

                        // recurse into complex types 
                        if (false == isScalar)
                        {
                            CreateVariableConstraintsRecursion(childPath.EdmType, childPath, domainMap, edmItemCollection);
                        } 
                    }
                } 
            } 
        }
 
        private static BoolExpression CreateIsOfTypeCondition(MemberPath currentPath, IEnumerable derivedTypes, MemberDomainMap domainMap)
        {
            Domain typeDomain = new Domain(derivedTypes.Select(derivedType => (Constant)new TypeConstant(derivedType)), domainMap.GetDomain(currentPath));
            BoolExpression typeCondition = BoolExpression.CreateLiteral(new TypeRestriction(new MemberProjectedSlot(currentPath), typeDomain), domainMap); 
            return typeCondition;
        } 
    } 
}

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