Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / CellQuery.cs / 1305376 / CellQuery.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.Utils; using System.Collections.Generic; using System.Data.Mapping.ViewGeneration.Validation; using System.Text; using System.Diagnostics; using System.Collections.ObjectModel; using System.Data.Mapping.ViewGeneration.Utils; using System.Data.Mapping.ViewGeneration.CqlGeneration; using System.Data.Metadata.Edm; using System.Linq; namespace System.Data.Mapping.ViewGeneration.Structures { using AttributeSet = Set; using System.Data.Entity; // This class stores the C or S query. For example, // (C) SELECT (p type Person) AS D1, p.pid, p.name FROM p in P WHERE D1 // (S) SELECT True AS D1, pid, name FROM SPerson WHERE D1 // // The cell query is stored in a "factored" manner for ease of // cell-merging and cell manipulation. It contains: // * Projection: A sequence of slots and a sequence of boolean slots (one // for each cell in the extent) // * A From part represented as a Join tree // * A where clause internal class CellQuery : InternalBase { #region Fields // Whether query has a 'SELECT DISTINCT' on top internal enum SelectDistinct { Yes, No } // The boolean expressions that essentially capture the type information // Fixed-size list; NULL in the list means 'unused' private List m_boolExprs; // The fields including the key fields // May contain NULLs - means 'not in the projection' private ProjectedSlot[] m_projectedSlots; // where clause: An expression formed using the boolExprs private BoolExpression m_whereClause; private BoolExpression m_originalWhereClause; // m_originalWhereClause is not changed private SelectDistinct m_selectDistinct; // The from part of the query private MemberPath m_extentMemberPath; // The basic cell relation for all slots in this private BasicCellRelation m_basicCellRelation; #endregion #region Constructors // effects: Creates a cell query with the given projection (slots), // from part (joinTreeRoot) and the predicate (whereClause) // Used for cell creation internal CellQuery(List slots, BoolExpression whereClause, MemberPath rootMember, SelectDistinct eliminateDuplicates) : this(slots.ToArray(), whereClause, new List (), eliminateDuplicates, rootMember) { } // effects: Given all the fields, just sets them. internal CellQuery(ProjectedSlot[] projectedSlots, BoolExpression whereClause, List boolExprs, SelectDistinct elimDupl, MemberPath rootMember) { m_boolExprs = boolExprs; m_projectedSlots = projectedSlots; m_whereClause = whereClause; m_originalWhereClause = whereClause; m_selectDistinct = elimDupl; m_extentMemberPath = rootMember; } /// /// Copy Constructor /// internal CellQuery(CellQuery source) { this.m_basicCellRelation = source.m_basicCellRelation; this.m_boolExprs = source.m_boolExprs; this.m_selectDistinct = source.m_selectDistinct; this.m_extentMemberPath = source.m_extentMemberPath; this.m_originalWhereClause = source.m_originalWhereClause; this.m_projectedSlots = source.m_projectedSlots; this.m_whereClause = source.m_whereClause; } // effects: Given an existing cellquery, makes a new one based on it // but uses the slots as specified with newSlots private CellQuery(CellQuery existing, ProjectedSlot[] newSlots) : this(newSlots, existing.m_whereClause, existing.m_boolExprs, existing.m_selectDistinct, existing.m_extentMemberPath) { } #endregion #region Properties internal SelectDistinct SelectDistinctFlag { get { return m_selectDistinct; } } // effects: Returns the top levelextent corresponding to this cell query internal EntitySetBase Extent { get { EntitySetBase extent = m_extentMemberPath.Extent as EntitySetBase; Debug.Assert(extent != null, "JoinTreeRoot in cellquery must be an extent"); return extent; } } // effects: Returns the number of slots projected in the query internal int NumProjectedSlots { get { return m_projectedSlots.Length; } } internal ProjectedSlot[] ProjectedSlots { get { return m_projectedSlots; } } internal ListBoolVars { get { return m_boolExprs; } } // effects: Returns the number of boolean expressions projected in the query internal int NumBoolVars { get { return m_boolExprs.Count; } } internal BoolExpression WhereClause { get { return m_whereClause; } } // effects: Returns the root of the join tree internal MemberPath SourceExtentMemberPath { get { return m_extentMemberPath; } } // effects: Returns the relation that contains all the slots present // in this cell query internal BasicCellRelation BasicCellRelation { get { Debug.Assert(m_basicCellRelation != null, "BasicCellRelation must be created first"); return m_basicCellRelation; } } /// /// [WARNING} /// After cell merging boolean expression can (most likely) have disjunctions (OR node) /// to represent the condition that a tuple came from either of the merged cells. /// In this case original where clause IS MERGED CLAUSE with OR!!! /// So don't call this after merging. It'll throw or debug assert from within GetConjunctsFromWC() /// internal IEnumerableConditions { get { return GetConjunctsFromOriginalWhereClause(); } } #endregion #region ProjectedSlots related methods // effects: Returns the slotnum projected slot internal ProjectedSlot ProjectedSlotAt(int slotNum) { Debug.Assert(slotNum < m_projectedSlots.Length, "Slot number too high"); return m_projectedSlots[slotNum]; } // requires: All slots in this are join tree slots // This method is called for an S-side query // cQuery is the corresponding C-side query in the cell // sourceCell is the original cell for "this" and cQuery // effects: Checks if any of the columns in "this" are mapped to multiple properties in cQuery. If so, // returns an error record about the duplicated slots internal ErrorLog.Record CheckForDuplicateFields(CellQuery cQuery, Cell sourceCell) { // slotMap stores the slots on the S-side and the // C-side properties that it maps to KeyToListMap slotMap = new KeyToListMap (MemberProjectedSlot.SpecificEqualityComparer); // Note that this does work for self-association. In the manager // employee example, ManagerId and EmployeeId from the SEmployee // table map to the two ends -- Manager.ManagerId and // Employee.EmployeeId in the C Space for (int i = 0; i < m_projectedSlots.Length; i++) { ProjectedSlot projectedSlot = m_projectedSlots[i]; MemberProjectedSlot slot = projectedSlot as MemberProjectedSlot; Debug.Assert(slot != null, "All slots for this method must be JoinTreeSlots"); slotMap.Add(slot, i); } StringBuilder builder = null; // Now determine the entries that have more than one integer per slot bool isErrorSituation = false; foreach (MemberProjectedSlot slot in slotMap.Keys) { ReadOnlyCollection indexes = slotMap.ListForKey(slot); Debug.Assert(indexes.Count >= 1, "Each slot must have one index at least"); if (indexes.Count > 1 && cQuery.AreSlotsEquivalentViaRefConstraints(indexes) == false) { // The column is mapped to more than one property and it // failed the "association corresponds to referential // constraints" check isErrorSituation = true; if (builder == null) { builder = new StringBuilder(System.Data.Entity.Strings.ViewGen_Duplicate_CProperties_0(Extent.Name)); builder.AppendLine(); } StringBuilder tmpBuilder = new StringBuilder(); for (int i = 0; i < indexes.Count; i++) { int index = indexes[i]; if (i != 0) { tmpBuilder.Append(", "); } // The slot must be a JoinTreeSlot. If it isn't it is an internal error MemberProjectedSlot cSlot = (MemberProjectedSlot)cQuery.m_projectedSlots[index]; tmpBuilder.Append(cSlot.ToUserString()); } builder.AppendLine(Strings.ViewGen_Duplicate_CProperties_IsMapped_1(slot.ToUserString(), tmpBuilder.ToString())); } } if (false == isErrorSituation) { return null; } ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.DuplicateCPropertiesMapped, builder.ToString(), sourceCell, String.Empty); return record; } // requires: "this" is a query on the C-side // and cSideSlotIndexes corresponds to the indexes // (into "this") that the slot is being mapped into // cSideSlotIndexes.Count > 1 - that is, a particular column in "this"'s corresponding S-Query // has been mapped to more than one property in "this" // // effects: Checks that the multiple mappings on the C-side are // backed by an appropriate Referential constraint // If a column is mapped to two properties in a single cell: // (a) Must be an association // (b) The two properties must be on opposite ends of the association // (c) The association must have a RI constraint // (d) Ordinal[A] == Ordinal[B] in the RI constraint // (c) and (d) can be stated as - the slots are equivalent, i.e., // kept equal via an RI constraint private bool AreSlotsEquivalentViaRefConstraints(ReadOnlyCollection cSideSlotIndexes) { // Check (a): Must be an association AssociationSet assocSet = Extent as AssociationSet; if (assocSet == null) { return false; } // Check (b): The two properties must be on opposite ends of the association // There better be exactly two properties! Debug.Assert(cSideSlotIndexes.Count > 1, "Method called when no duplicate mapping"); if (cSideSlotIndexes.Count > 2) { return false; } // They better be join tree slots (if they are mapped!) and map to opposite ends MemberProjectedSlot slot0 = (MemberProjectedSlot)m_projectedSlots[cSideSlotIndexes[0]]; MemberProjectedSlot slot1 = (MemberProjectedSlot)m_projectedSlots[cSideSlotIndexes[1]]; return slot0.MemberPath.IsEquivalentViaRefConstraint(slot1.MemberPath); } // requires: The Where clause satisfies the same requirements a GetConjunctsFromWhereClause // effects: For each slot that has a NotNull condition in the where // clause, checks if it is projected. If all such slots are // projected, returns null. Else returns an error record internal ErrorLog.Record CheckForProjectedNotNullSlots(Cell sourceCell, IEnumerable associationSets) { StringBuilder builder = new StringBuilder(); bool foundError = false; foreach (MemberRestriction restriction in Conditions) { if (restriction.Domain.ContainsNotNull()) { MemberProjectedSlot slot = MemberProjectedSlot.GetSlotForMember(m_projectedSlots, restriction.RestrictedMemberSlot.MemberPath); if (slot == null) //member with not null condition is not mapped in this extent { bool missingMapping = true; if(Extent is EntitySet) { bool isCQuery = sourceCell.CQuery == this; ViewTarget target = isCQuery ? ViewTarget.QueryView : ViewTarget.UpdateView; CellQuery rightCellQuery = isCQuery? sourceCell.SQuery : sourceCell.CQuery; //Find out if there is an association mapping but only if the current Not Null condition is on an EntitySet EntitySet rightExtent = rightCellQuery.Extent as EntitySet; if (rightExtent != null) { List | associations = MetadataHelper.GetAssociationsForEntitySet(rightCellQuery.Extent as EntitySet); foreach (var association in associations .Where(association => association.AssociationSetEnds.Where(end => end.EntitySet != rightCellQuery.Extent).First().CorrespondingAssociationEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One)) { foreach (var associationCell in associationSets.Where(c => c.GetRightQuery(target).Extent.EdmEquals(association))) { if (MemberProjectedSlot.GetSlotForMember(associationCell.GetLeftQuery(target).ProjectedSlots, restriction.RestrictedMemberSlot.MemberPath) != null) { missingMapping = false; } } } } } if (missingMapping) { // condition of NotNull and slot not being projected builder.AppendLine(System.Data.Entity.Strings.ViewGen_NotNull_No_Projected_Slot_0( restriction.RestrictedMemberSlot.MemberPath.PathToString(false))); foundError = true; } } } } if (false == foundError) { return null; } ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.NotNullNoProjectedSlot, builder.ToString(), sourceCell, String.Empty); return record; } internal void FixMissingSlotAsDefaultConstant(int slotNumber, ConstantProjectedSlot slot) { Debug.Assert(m_projectedSlots[slotNumber] == null, "Another attempt to plug in a default value"); m_projectedSlots[slotNumber] = slot; } // requires: projectedSlotMap which contains a mapping of the fields // for "this" to integers // effects: Align the fields of this cell query using the // projectedSlotMap and generates a new query into newMainQuery // Based on the re-aligned fields in this, re-aligns the // corresponding fields in otherQuery as well and modifies // newOtherQuery to contain it // Example: // input: Proj[A,B,"5"] = Proj[F,"7",G] // Proj[C,B] = Proj[H,I] // projectedSlotMap: A -> 0, B -> 1, C -> 2 // output: Proj[A,B,null] = Proj[F,"7",null] // Proj[null,B,C] = Proj[null,I,H] internal void CreateFieldAlignedCellQueries(CellQuery otherQuery, MemberProjectionIndex projectedSlotMap, out CellQuery newMainQuery, out CellQuery newOtherQuery) { // mainSlots and otherSlots hold the new slots for two queries int numAlignedSlots = projectedSlotMap.Count; ProjectedSlot[] mainSlots = new ProjectedSlot[numAlignedSlots]; ProjectedSlot[] otherSlots = new ProjectedSlot[numAlignedSlots]; // Go through the slots for this query and find the new slot for them for (int i = 0; i < m_projectedSlots.Length; i++) { MemberProjectedSlot slot = m_projectedSlots[i] as MemberProjectedSlot; Debug.Assert(slot != null, "All slots during cell normalization must field slots"); // Get the the ith slot's variable and then get the // new slot number from the field map int newSlotNum = projectedSlotMap.IndexOf(slot.MemberPath); Debug.Assert(newSlotNum >= 0, "Field projected but not in projectedSlotMap"); mainSlots[newSlotNum] = m_projectedSlots[i]; otherSlots[newSlotNum] = otherQuery.m_projectedSlots[i]; // We ignore constants -- note that this is not the // isHighpriority or discriminator case. An example of this // is when (say) Address does not have zip but USAddress // does. Then the constraint looks like Pi_NULL, A, B(E) = // Pi_x, y, z(S) // We don't care about this null in the view generation of // the left side. Note that this could happen in inheritance // or in cases when say the S side has 20 fields but the C // side has only 3 - the other 17 are null or default. // NOTE: We allow such constants only on the C side and not // ont the S side. Otherwise, we can have a situation Pi_A, // B, C(E) = Pi_5, y, z(S) Then someone can set A to 7 and we // will not roundtrip. We check for this in validation } // Make the new cell queries with the new slots newMainQuery = new CellQuery(this, mainSlots); newOtherQuery = new CellQuery(otherQuery, otherSlots); } // requires: All slots in this are null or non-constants // effects: Returns the non-null slots of this internal AttributeSet GetNonNullSlots() { AttributeSet attributes = new AttributeSet(MemberPath.EqualityComparer); foreach (ProjectedSlot projectedSlot in m_projectedSlots) { // null means 'unused' slot -- we ignore those if (projectedSlot != null) { MemberProjectedSlot projectedVar = projectedSlot as MemberProjectedSlot; Debug.Assert(projectedVar != null, "Projected slot must not be a constant"); attributes.Add(projectedVar.MemberPath); } } return attributes; } // effects: Returns an error record if the keys of the extent/associationSet being mapped are // present in the projected slots of this query. Returns null // otherwise. ownerCell indicates the cell that owns this and // resourceString is a resource used for error messages internal ErrorLog.Record VerifyKeysPresent(Cell ownerCell, Func
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataGridTextBox.cs
- Misc.cs
- DbConvert.cs
- URI.cs
- DataGridViewCellCancelEventArgs.cs
- SqlDataSourceDesigner.cs
- InvalidPrinterException.cs
- ObjectNavigationPropertyMapping.cs
- RepeatInfo.cs
- MatrixAnimationBase.cs
- OracleRowUpdatingEventArgs.cs
- WebScriptEndpoint.cs
- ListBindingConverter.cs
- SelectionProcessor.cs
- EventPropertyMap.cs
- RSAPKCS1KeyExchangeFormatter.cs
- SourceElementsCollection.cs
- StructuredType.cs
- Soap12ProtocolReflector.cs
- HttpWebRequestElement.cs
- HttpRequest.cs
- ConfigDefinitionUpdates.cs
- RepeaterItemEventArgs.cs
- LinkLabel.cs
- HtmlShim.cs
- Stackframe.cs
- HelloMessageApril2005.cs
- BaseConfigurationRecord.cs
- ResourcesChangeInfo.cs
- RewritingProcessor.cs
- ReferentialConstraint.cs
- CookieParameter.cs
- HWStack.cs
- EdmSchemaError.cs
- Expression.cs
- URLAttribute.cs
- ScriptControl.cs
- ErrorHandler.cs
- IncrementalReadDecoders.cs
- EraserBehavior.cs
- CompilerErrorCollection.cs
- EntitySetRetriever.cs
- RowParagraph.cs
- Floater.cs
- AsyncOperationContext.cs
- AppDomainUnloadedException.cs
- TouchFrameEventArgs.cs
- Stroke2.cs
- DescriptionAttribute.cs
- CodeParameterDeclarationExpression.cs
- SiteMapPath.cs
- TranslateTransform.cs
- Helper.cs
- HtmlTableCellCollection.cs
- Delegate.cs
- DateBoldEvent.cs
- GenericXmlSecurityToken.cs
- NavigationWindowAutomationPeer.cs
- HttpPostedFile.cs
- TextServicesDisplayAttributePropertyRanges.cs
- EncryptedData.cs
- DataListCommandEventArgs.cs
- GridProviderWrapper.cs
- SiteMapProvider.cs
- TypeConverterHelper.cs
- PerformanceCounterPermissionEntry.cs
- DataSvcMapFileSerializer.cs
- DeferredElementTreeState.cs
- NavigationPropertySingletonExpression.cs
- SqlCachedBuffer.cs
- HotSpotCollection.cs
- OracleDateTime.cs
- TextContainerChangedEventArgs.cs
- ImpersonationContext.cs
- DataViewManagerListItemTypeDescriptor.cs
- SectionInput.cs
- SizeAnimation.cs
- SessionEndingEventArgs.cs
- MsmqIntegrationProcessProtocolHandler.cs
- FormsAuthenticationConfiguration.cs
- DataServiceContext.cs
- HideDisabledControlAdapter.cs
- DomNameTable.cs
- SchemaDeclBase.cs
- RedirectionProxy.cs
- ProfilePropertySettingsCollection.cs
- ValueExpressions.cs
- XmlSerializerFactory.cs
- ipaddressinformationcollection.cs
- MatrixStack.cs
- MissingMemberException.cs
- HwndStylusInputProvider.cs
- path.cs
- ParameterBuilder.cs
- Viewport2DVisual3D.cs
- ExpressionParser.cs
- NumberFunctions.cs
- BeginStoryboard.cs
- NegotiationTokenAuthenticatorState.cs
- TextElementAutomationPeer.cs