public static bool FindMappingErrors(ViewgenContext context, MemberDomainMap domainMap, ErrorLog errorLog) { //Can't get here if Update Views have validation disabled Debug.Assert(context.ViewTarget == ViewTarget.QueryView || context.Config.IsValidationEnabled); if (context.ViewTarget == ViewTarget.QueryView && !context.Config.IsValidationEnabled) { return(false); // Rules for QV under no validation are different } var matcher = new ErrorPatternMatcher(context, domainMap, errorLog); matcher.MatchMissingMappingErrors(); matcher.MatchConditionErrors(); matcher.MatchSplitErrors(); if (matcher.m_errorLog.Count == matcher.m_originalErrorCount) { //this will generate redundant errors if one of the above routine finds an error // so execute it only when we dont have any other errors matcher.MatchPartitionErrors(); } if (matcher.m_errorLog.Count > matcher.m_originalErrorCount) { ExceptionHelpers.ThrowMappingException(matcher.m_errorLog, matcher.m_viewgenContext.Config); } return(false); }
internal QueryRewriter(EdmType generatedType, ViewgenContext context, ViewGenMode typesGenerationMode) { Debug.Assert(typesGenerationMode != ViewGenMode.GenerateAllViews); _typesGenerationMode = typesGenerationMode; _context = context; _generatedType = generatedType; _domainMap = context.MemberMaps.LeftDomainMap; _config = context.Config; _identifiers = context.CqlIdentifiers; _qp = new RewritingProcessor<Tile<FragmentQuery>>(new DefaultTileProcessor<FragmentQuery>(context.LeftFragmentQP)); _extentPath = new MemberPath(context.Extent); _keyAttributes = new List<MemberPath>(MemberPath.GetKeyMembers(context.Extent, _domainMap)); // populate _fragmentQueries and _views foreach (var leftCellWrapper in _context.AllWrappersForExtent) { var query = leftCellWrapper.FragmentQuery; Tile<FragmentQuery> tile = CreateTile(query); _fragmentQueries.Add(query); _views.Add(tile); } Debug.Assert(_views.Count > 0); AdjustMemberDomainsForUpdateViews(); // must be done after adjusting domains _domainQuery = GetDomainQuery(FragmentQueries, generatedType); _usedViews = new HashSet<FragmentQuery>(); }
internal QueryRewriter( EdmType generatedType, ViewgenContext context, ViewGenMode typesGenerationMode) { this._typesGenerationMode = typesGenerationMode; this._context = context; this._generatedType = generatedType; this._domainMap = context.MemberMaps.LeftDomainMap; this._config = context.Config; this._identifiers = context.CqlIdentifiers; this._qp = new RewritingProcessor <Tile <FragmentQuery> >((TileProcessor <Tile <FragmentQuery> >) new DefaultTileProcessor <FragmentQuery>((TileQueryProcessor <FragmentQuery>)context.LeftFragmentQP)); this._extentPath = new MemberPath(context.Extent); this._keyAttributes = new List <MemberPath>(MemberPath.GetKeyMembers(context.Extent, this._domainMap)); foreach (LeftCellWrapper leftCellWrapper in this._context.AllWrappersForExtent) { FragmentQuery fragmentQuery = leftCellWrapper.FragmentQuery; Tile <FragmentQuery> tile = (Tile <FragmentQuery>)QueryRewriter.CreateTile(fragmentQuery); this._fragmentQueries.Add(fragmentQuery); this._views.Add(tile); } this.AdjustMemberDomainsForUpdateViews(); this._domainQuery = this.GetDomainQuery(this.FragmentQueries, generatedType); this._usedViews = new HashSet <FragmentQuery>(); }
// effects: Creates a node with operation opType and no children internal OpCellTreeNode(ViewgenContext context, CellTreeOpType opType) : base(context) { m_opType = opType; m_attrs = new AttributeSet(MemberPath.EqualityComparer); m_children = new List <CellTreeNode>(); }
internal static CellTreeNode TileToCellTree( Tile <FragmentQuery> tile, ViewgenContext context) { if (tile.OpKind == TileOpKind.Named) { FragmentQuery view = ((TileNamed <FragmentQuery>)tile).NamedQuery; LeftCellWrapper cellWrapper = context.AllWrappersForExtent.First <LeftCellWrapper>((Func <LeftCellWrapper, bool>)(w => w.FragmentQuery == view)); return((CellTreeNode) new LeafCellTreeNode(context, cellWrapper)); } CellTreeOpType opType; switch (tile.OpKind) { case TileOpKind.Union: opType = CellTreeOpType.Union; break; case TileOpKind.Join: opType = CellTreeOpType.IJ; break; case TileOpKind.AntiSemiJoin: opType = CellTreeOpType.LASJ; break; default: return((CellTreeNode)null); } return((CellTreeNode) new OpCellTreeNode(context, opType, new CellTreeNode[2] { QueryRewriter.TileToCellTree(tile.Arg1, context), QueryRewriter.TileToCellTree(tile.Arg2, context) })); }
internal LeafCellTreeNode(ViewgenContext context, LeftCellWrapper cellWrapper, FragmentQuery rightFragmentQuery) : base(context) { m_cellWrapper = cellWrapper; m_leftFragmentQuery = cellWrapper.FragmentQuery; m_rightFragmentQuery = rightFragmentQuery; }
private static FragmentQuery GenerateFragmentQuery( IEnumerable <CellTreeNode> children, bool isLeft, ViewgenContext context, CellTreeOpType OpType) { FragmentQuery fragmentQuery1 = isLeft ? children.First <CellTreeNode>().LeftFragmentQuery : children.First <CellTreeNode>().RightFragmentQuery; FragmentQueryProcessor fragmentQueryProcessor = isLeft ? context.LeftFragmentQP : context.RightFragmentQP; foreach (CellTreeNode cellTreeNode in children.Skip <CellTreeNode>(1)) { FragmentQuery fragmentQuery2 = isLeft ? cellTreeNode.LeftFragmentQuery : cellTreeNode.RightFragmentQuery; switch (OpType) { case CellTreeOpType.LOJ: continue; case CellTreeOpType.IJ: fragmentQuery1 = fragmentQueryProcessor.Intersect(fragmentQuery1, fragmentQuery2); continue; case CellTreeOpType.LASJ: fragmentQuery1 = fragmentQueryProcessor.Difference(fragmentQuery1, fragmentQuery2); continue; default: fragmentQuery1 = fragmentQueryProcessor.Union(fragmentQuery1, fragmentQuery2); continue; } } return(fragmentQuery1); }
internal OpCellTreeNode( ViewgenContext context, CellTreeOpType opType, params CellTreeNode[] children) : this(context, opType, (IEnumerable <CellTreeNode>)children) { }
internal OpCellTreeNode(ViewgenContext context, CellTreeOpType opType) : base(context) { this.m_opType = opType; this.m_attrs = new Set <MemberPath>(MemberPath.EqualityComparer); this.m_children = new List <CellTreeNode>(); }
// requires: constraint.ChildColumns form a key in // constraint.ChildTable (actually they should subsume the primary key) private void GuaranteeForeignKeyConstraintInCSpace(QueryRewriter childRewriter, QueryRewriter parentRewriter, ErrorLog errorLog, ConfigViewGenerator config) { ViewgenContext childContext = childRewriter.ViewgenContext; ViewgenContext parentContext = parentRewriter.ViewgenContext; CellTreeNode cNode = childRewriter.BasicView; CellTreeNode pNode = parentRewriter.BasicView; FragmentQueryProcessor qp = FragmentQueryProcessor.Merge(childContext.RightFragmentQP, parentContext.RightFragmentQP); bool cImpliesP = qp.IsContainedIn(cNode.RightFragmentQuery, pNode.RightFragmentQuery); if (false == cImpliesP) { // Foreign key constraint not being ensured in C-space string childExtents = LeftCellWrapper.GetExtentListAsUserString(cNode.GetLeaves()); string parentExtents = LeftCellWrapper.GetExtentListAsUserString(pNode.GetLeaves()); string message = System.Data.Entity.Strings.ViewGen_Foreign_Key_Not_Guaranteed_InCSpace( ToUserString()); // Add all wrappers into allWrappers Set <LeftCellWrapper> allWrappers = new Set <LeftCellWrapper>(pNode.GetLeaves()); allWrappers.AddRange(cNode.GetLeaves()); ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ForeignKeyNotGuaranteedInCSpace, message, allWrappers, String.Empty); errorLog.AddEntry(record); } }
private static FragmentQuery GenerateFragmentQuery( IEnumerable <CellTreeNode> children, bool isLeft, ViewgenContext context, CellTreeOpType OpType) { Debug.Assert(children.Any()); var fragmentQuery = isLeft ? children.First().LeftFragmentQuery : children.First().RightFragmentQuery; var qp = isLeft ? context.LeftFragmentQP : context.RightFragmentQP; foreach (var child in children.Skip(1)) { var nextQuery = isLeft ? child.LeftFragmentQuery : child.RightFragmentQuery; switch (OpType) { case CellTreeOpType.IJ: fragmentQuery = qp.Intersect(fragmentQuery, nextQuery); break; case CellTreeOpType.LOJ: // Left outer join means keeping the domain of the leftmost child break; case CellTreeOpType.LASJ: // not used in basic view generation but current validation calls Simplify, so add this for debugging fragmentQuery = qp.Difference(fragmentQuery, nextQuery); break; default: // All other operators (Union, FOJ) require union of the domains fragmentQuery = qp.Union(fragmentQuery, nextQuery); break; } } return(fragmentQuery); }
internal static void CheckConstraints(CellTreeNode node, LeftCellWrapper wrapper, ViewgenContext context, ErrorLog errorLog) { DomainConstraintVisitor visitor = new DomainConstraintVisitor(wrapper, context, errorLog); node.Accept <bool, bool>(visitor, true); }
internal WhereClauseVisitor( CellTreeNode topLevelTree, Dictionary <RewritingValidator.MemberValueBinding, CellTreeNode> memberValueTrees) { this._topLevelTree = topLevelTree; this._memberValueTrees = memberValueTrees; this._viewgenContext = topLevelTree.ViewgenContext; }
internal RewritingValidator(ViewgenContext context, CellTreeNode basicView) { _viewgenContext = context; _basicView = basicView; _domainMap = _viewgenContext.MemberMaps.UpdateDomainMap; _keyAttributes = MemberPath.GetKeyMembers(_viewgenContext.Extent, _domainMap); _errorLog = new ErrorLog(); }
private ErrorPatternMatcher(ViewgenContext context, MemberDomainMap domainMap, ErrorLog errorLog) { m_viewgenContext = context; m_domainMap = domainMap; MemberPath.GetKeyMembers(context.Extent, domainMap); m_errorLog = errorLog; m_originalErrorCount = m_errorLog.Count; }
// effects: Given a sequence of children node and the opType, creates // an OpCellTreeNode and returns it internal OpCellTreeNode(ViewgenContext context, CellTreeOpType opType, IEnumerable <CellTreeNode> children) : this(context, opType) { // Add the children one by one so that we can get the attrs etc fixed foreach (CellTreeNode child in children) { Add(child); } }
private DomainConstraintVisitor( LeftCellWrapper wrapper, ViewgenContext context, ErrorLog errorLog) { this.m_wrapper = wrapper; this.m_viewgenContext = context; this.m_errorLog = errorLog; }
internal static void CheckConstraints( CellTreeNode node, LeftCellWrapper wrapper, ViewgenContext context, ErrorLog errorLog) { RewritingValidator.DomainConstraintVisitor constraintVisitor = new RewritingValidator.DomainConstraintVisitor(wrapper, context, errorLog); node.Accept <bool, bool>((CellTreeNode.SimpleCellTreeVisitor <bool, bool>)constraintVisitor, true); }
// effects: Encapsulate the cell wrapper in the node internal LeafCellTreeNode(ViewgenContext context, LeftCellWrapper cellWrapper) : base(context) { m_cellWrapper = cellWrapper; cellWrapper.AssertHasUniqueCell(); m_rightFragmentQuery = FragmentQuery.Create( cellWrapper.OriginalCellNumberString, cellWrapper.CreateRoleBoolean(), cellWrapper.RightCellQuery); }
private bool CompareS( ErrorPatternMatcher.ComparisonOP op, ViewgenContext context, LeftCellWrapper leftWrapper1, LeftCellWrapper leftWrapper2, FragmentQuery rightQuery1, FragmentQuery rightQuery2) { return(this.Compare(false, op, context, leftWrapper1, leftWrapper2, rightQuery1, rightQuery2)); }
internal OpCellTreeNode( ViewgenContext context, CellTreeOpType opType, IEnumerable <CellTreeNode> children) : this(context, opType) { foreach (CellTreeNode child in children) { this.Add(child); } }
private bool CheckIfConstraintMappedToForeignKeyAssociation( QueryRewriter childRewriter, QueryRewriter parentRewriter, Set <Cell> cells) { ViewgenContext viewgenContext1 = childRewriter.ViewgenContext; ViewgenContext viewgenContext2 = parentRewriter.ViewgenContext; List <Set <EdmProperty> > source1 = new List <Set <EdmProperty> >(); List <Set <EdmProperty> > source2 = new List <Set <EdmProperty> >(); foreach (Cell cell in cells) { if (cell.CQuery.Extent.BuiltInTypeKind != BuiltInTypeKind.AssociationSet) { Set <EdmProperty> cslotsForTableColumns1 = cell.GetCSlotsForTableColumns(this.ChildColumns); if (cslotsForTableColumns1 != null && cslotsForTableColumns1.Count != 0) { source1.Add(cslotsForTableColumns1); } Set <EdmProperty> cslotsForTableColumns2 = cell.GetCSlotsForTableColumns(this.ParentColumns); if (cslotsForTableColumns2 != null && cslotsForTableColumns2.Count != 0) { source2.Add(cslotsForTableColumns2); } } } if (source1.Count != 0 && source2.Count != 0) { foreach (AssociationType associationType in viewgenContext1.EntityContainerMapping.EdmEntityContainer.BaseEntitySets.OfType <AssociationSet>().Where <AssociationSet>((Func <AssociationSet, bool>)(it => it.ElementType.IsForeignKey)).Select <AssociationSet, AssociationType>((Func <AssociationSet, AssociationType>)(it => it.ElementType))) { ReferentialConstraint refConstraint = associationType.ReferentialConstraints.FirstOrDefault <ReferentialConstraint>(); IEnumerable <Set <EdmProperty> > source3 = source1.Where <Set <EdmProperty> >((Func <Set <EdmProperty>, bool>)(it => it.SetEquals(new Set <EdmProperty>((IEnumerable <EdmProperty>)refConstraint.ToProperties)))); IEnumerable <Set <EdmProperty> > source4 = source2.Where <Set <EdmProperty> >((Func <Set <EdmProperty>, bool>)(it => it.SetEquals(new Set <EdmProperty>((IEnumerable <EdmProperty>)refConstraint.FromProperties)))); if (source3.Count <Set <EdmProperty> >() != 0 && source4.Count <Set <EdmProperty> >() != 0) { foreach (IEnumerable <EdmProperty> properties1_1 in source4) { Set <int> propertyIndexes = ForeignConstraint.GetPropertyIndexes(properties1_1, refConstraint.FromProperties); foreach (IEnumerable <EdmProperty> properties1_2 in source3) { if (ForeignConstraint.GetPropertyIndexes(properties1_2, refConstraint.ToProperties).SequenceEqual <int>((IEnumerable <int>)propertyIndexes)) { return(true); } } } } } } return(false); }
private static bool CheckConstraintWhenOnlyParentMapped( AssociationSet assocSet, AssociationEndMember endMember, QueryRewriter childRewriter, QueryRewriter parentRewriter) { ViewgenContext viewgenContext1 = childRewriter.ViewgenContext; ViewgenContext viewgenContext2 = parentRewriter.ViewgenContext; CellTreeNode basicView = parentRewriter.BasicView; RoleBoolean roleBoolean = new RoleBoolean(assocSet.AssociationSetEnds[endMember.Name]); BoolExpression whereClause = basicView.RightFragmentQuery.Condition.Create((BoolLiteral)roleBoolean); FragmentQuery q1 = FragmentQuery.Create((IEnumerable <MemberPath>)basicView.RightFragmentQuery.Attributes, whereClause); return(FragmentQueryProcessor.Merge(viewgenContext1.RightFragmentQP, viewgenContext2.RightFragmentQP).IsContainedIn(q1, basicView.RightFragmentQuery)); }
private static List <LeftCellWrapper> GetWrappersFromContext(ViewgenContext context, EntitySetBase extent) { List <LeftCellWrapper> wrappers; if (context == null) { wrappers = new List <LeftCellWrapper>(); } else { Debug.Assert(context.Extent.Equals(extent), "ViewgenContext extent and expected extent different"); wrappers = context.AllWrappersForExtent; } return(wrappers); }
private bool Compare( bool lookingForC, ErrorPatternMatcher.ComparisonOP op, ViewgenContext context, LeftCellWrapper leftWrapper1, LeftCellWrapper leftWrapper2, FragmentQuery rightQuery1, FragmentQuery rightQuery2) { if (lookingForC && this.IsQueryView() || !lookingForC && !this.IsQueryView()) { LCWComparer lcwComparer; switch (op) { case ErrorPatternMatcher.ComparisonOP.IsContainedIn: lcwComparer = new LCWComparer(context.LeftFragmentQP.IsContainedIn); break; case ErrorPatternMatcher.ComparisonOP.IsDisjointFrom: lcwComparer = new LCWComparer(context.LeftFragmentQP.IsDisjointFrom); break; default: return(false); } return(lcwComparer(leftWrapper1.FragmentQuery, leftWrapper2.FragmentQuery)); } LCWComparer lcwComparer1; switch (op) { case ErrorPatternMatcher.ComparisonOP.IsContainedIn: lcwComparer1 = new LCWComparer(context.RightFragmentQP.IsContainedIn); break; case ErrorPatternMatcher.ComparisonOP.IsDisjointFrom: lcwComparer1 = new LCWComparer(context.RightFragmentQP.IsDisjointFrom); break; default: return(false); } return(lcwComparer1(rightQuery1, rightQuery2)); }
private bool Compare( bool lookingForC, ComparisonOP op, ViewgenContext context, LeftCellWrapper leftWrapper1, LeftCellWrapper leftWrapper2, FragmentQuery rightQuery1, FragmentQuery rightQuery2) { LCWComparer comparer; if ((lookingForC && IsQueryView()) || (!lookingForC && !IsQueryView())) { if (op == ComparisonOP.IsContainedIn) { comparer = context.LeftFragmentQP.IsContainedIn; } else if (op == ComparisonOP.IsDisjointFrom) { comparer = context.LeftFragmentQP.IsDisjointFrom; } else { Debug.Fail("Unexpected comparison operator, only IsDisjointFrom and IsContainedIn are expected"); return(false); } return(comparer(leftWrapper1.FragmentQuery, leftWrapper2.FragmentQuery)); } else { if (op == ComparisonOP.IsContainedIn) { comparer = context.RightFragmentQP.IsContainedIn; } else if (op == ComparisonOP.IsDisjointFrom) { comparer = context.RightFragmentQP.IsDisjointFrom; } else { Debug.Fail("Unexpected comparison operator, only IsDisjointFrom and IsContainedIn are expected"); return(false); } return(comparer(rightQuery1, rightQuery2)); } }
// requires: IsForeignKeySuperSetOfPrimaryKeyInChildTable() is false // and primaryKeys of ChildTable are not mapped in cell. cell // corresponds to an association set. parentSet is the set // corresponding to the end that we are looking at // effects: Checks if the constraint is correctly maintained in // C-space via an association set (being a subset of the // corresponding entitySet) private bool CheckConstraintWhenOnlyParentMapped(Cell cell, EntitySet parentSet, AssociationSet assocSet, AssociationEndMember endMember, QueryRewriter childRewriter, QueryRewriter parentRewriter, ConfigViewGenerator config) { ViewgenContext childContext = childRewriter.ViewgenContext; ViewgenContext parentContext = parentRewriter.ViewgenContext; CellTreeNode pNode = parentRewriter.BasicView; Debug.Assert(pNode != null); RoleBoolean endRoleBoolean = new RoleBoolean(assocSet.AssociationSetEnds[endMember.Name]); // use query in pNode as a factory to create a bool expression for the endRoleBoolean BoolExpression endCondition = pNode.RightFragmentQuery.Condition.Create(endRoleBoolean); FragmentQuery cNodeQuery = FragmentQuery.Create(pNode.RightFragmentQuery.Attributes, endCondition); FragmentQueryProcessor qp = FragmentQueryProcessor.Merge(childContext.RightFragmentQP, parentContext.RightFragmentQP); bool cImpliesP = qp.IsContainedIn(cNodeQuery, pNode.RightFragmentQuery); return(cImpliesP); }
private void GuaranteeForeignKeyConstraintInCSpace( QueryRewriter childRewriter, QueryRewriter parentRewriter, ErrorLog errorLog) { ViewgenContext viewgenContext1 = childRewriter.ViewgenContext; ViewgenContext viewgenContext2 = parentRewriter.ViewgenContext; CellTreeNode basicView1 = childRewriter.BasicView; CellTreeNode basicView2 = parentRewriter.BasicView; if (FragmentQueryProcessor.Merge(viewgenContext1.RightFragmentQP, viewgenContext2.RightFragmentQP).IsContainedIn(basicView1.RightFragmentQuery, basicView2.RightFragmentQuery)) { return; } LeftCellWrapper.GetExtentListAsUserString((IEnumerable <LeftCellWrapper>)basicView1.GetLeaves()); LeftCellWrapper.GetExtentListAsUserString((IEnumerable <LeftCellWrapper>)basicView2.GetLeaves()); string message = Strings.ViewGen_Foreign_Key_Not_Guaranteed_InCSpace((object)this.ToUserString()); Set <LeftCellWrapper> set = new Set <LeftCellWrapper>((IEnumerable <LeftCellWrapper>)basicView2.GetLeaves()); set.AddRange((IEnumerable <LeftCellWrapper>)basicView1.GetLeaves()); ErrorLog.Record record = new ErrorLog.Record(ViewGenErrorCode.ForeignKeyNotGuaranteedInCSpace, message, (IEnumerable <LeftCellWrapper>)set, string.Empty); errorLog.AddEntry(record); }
public static bool FindMappingErrors( ViewgenContext context, MemberDomainMap domainMap, ErrorLog errorLog) { if (context.ViewTarget == ViewTarget.QueryView && !context.Config.IsValidationEnabled) { return(false); } ErrorPatternMatcher errorPatternMatcher = new ErrorPatternMatcher(context, domainMap, errorLog); errorPatternMatcher.MatchMissingMappingErrors(); errorPatternMatcher.MatchConditionErrors(); errorPatternMatcher.MatchSplitErrors(); if (errorPatternMatcher.m_errorLog.Count == errorPatternMatcher.m_originalErrorCount) { errorPatternMatcher.MatchPartitionErrors(); } if (errorPatternMatcher.m_errorLog.Count > errorPatternMatcher.m_originalErrorCount) { ExceptionHelpers.ThrowMappingException(errorPatternMatcher.m_errorLog, errorPatternMatcher.m_viewgenContext.Config); } return(false); }
private static List<LeftCellWrapper> GetWrappersFromContext(ViewgenContext context, EntitySetBase extent) { List<LeftCellWrapper> wrappers; if (context == null) { wrappers = new List<LeftCellWrapper>(); } else { Debug.Assert(context.Extent.Equals(extent), "ViewgenContext extent and expected extent different"); wrappers = context.AllWrappersForExtent; } return wrappers; }
internal WhereClauseVisitor(CellTreeNode topLevelTree, Dictionary <MemberValueBinding, CellTreeNode> memberValueTrees) { _topLevelTree = topLevelTree; _memberValueTrees = memberValueTrees; _viewgenContext = topLevelTree.ViewgenContext; }
// allows us to check whether a found rewriting is satisfiable // by taking into account the "other side" of mapping constraints // (Ultimately, should produce a CQT and use general-purpose query containment) internal static CellTreeNode TileToCellTree(Tile<FragmentQuery> tile, ViewgenContext context) { if (tile.OpKind == TileOpKind.Named) { var view = ((TileNamed<FragmentQuery>)tile).NamedQuery; var leftCellWrapper = context.AllWrappersForExtent.First(w => w.FragmentQuery == view); return new LeafCellTreeNode(context, leftCellWrapper); } CellTreeOpType opType; switch (tile.OpKind) { case TileOpKind.Join: opType = CellTreeOpType.IJ; break; case TileOpKind.AntiSemiJoin: opType = CellTreeOpType.LASJ; break; case TileOpKind.Union: opType = CellTreeOpType.Union; break; default: Debug.Fail("unexpected"); return null; } return new OpCellTreeNode( context, opType, TileToCellTree(tile.Arg1, context), TileToCellTree(tile.Arg2, context)); }
private bool CheckIfConstraintMappedToForeignKeyAssociation(QueryRewriter childRewriter, QueryRewriter parentRewriter, Set <Cell> cells, ErrorLog errorLog) { ViewgenContext childContext = childRewriter.ViewgenContext; ViewgenContext parentContext = parentRewriter.ViewgenContext; //First collect the sets of properties that the principal and dependant ends of this FK //are mapped to in the Edm side. var childPropertiesSet = new List <Set <EdmProperty> >(); var parentPropertiesSet = new List <Set <EdmProperty> >(); foreach (Cell cell in cells) { if (cell.CQuery.Extent.BuiltInTypeKind != BuiltInTypeKind.AssociationSet) { var childProperties = cell.GetCSlotsForTableColumns(ChildColumns); if ((childProperties != null) && (childProperties.Count != 0)) { childPropertiesSet.Add(childProperties); } var parentProperties = cell.GetCSlotsForTableColumns(ParentColumns); if ((parentProperties != null) && (parentProperties.Count != 0)) { parentPropertiesSet.Add(parentProperties); } } } //Now Check if the properties on the Edm side are connected via an FK relationship. if ((childPropertiesSet.Count != 0) && (parentPropertiesSet.Count != 0)) { var foreignKeyAssociations = childContext.EntityContainerMapping.EdmEntityContainer.BaseEntitySets.OfType <AssociationSet>().Where(it => it.ElementType.IsForeignKey).Select(it => it.ElementType); foreach (AssociationType association in foreignKeyAssociations) { ReferentialConstraint refConstraint = association.ReferentialConstraints.FirstOrDefault(); //We need to check to see if the dependent properties that were mapped from S side are present as //dependant properties of this ref constraint on the Edm side. We need to do the same for principal side but //we can not enforce equality since the order of the properties participating in the constraint on the S side and //C side could be different. This is OK as long as they are mapped appropriately. We also can not use Existance as a sufficient //condition since it will allow invalid mapping where FK columns could have been flipped when mapping to the Edm side. So //we make sure that the index of the properties in the principal and dependant are same on the Edm side even if they are in //different order for ref constraints for Edm and store side. var childRefPropertiesCollection = childPropertiesSet.Where(it => it.SetEquals(new Set <EdmProperty>(refConstraint.ToProperties))); var parentRefPropertiesCollection = parentPropertiesSet.Where(it => it.SetEquals(new Set <EdmProperty>(refConstraint.FromProperties))); if ((childRefPropertiesCollection.Count() != 0 && parentRefPropertiesCollection.Count() != 0)) { foreach (var parentRefProperties in parentRefPropertiesCollection) { var parentIndexes = GetPropertyIndexes(parentRefProperties, refConstraint.FromProperties); foreach (var childRefProperties in childRefPropertiesCollection) { var childIndexes = GetPropertyIndexes(childRefProperties, refConstraint.ToProperties); if (childIndexes.SequenceEqual(parentIndexes)) { return(true); } } } } } } return(false); }