Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / CellQuery.cs / 1 / 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; 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 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, ExtentJoinTreeNode joinTreeRoot) : this(null, slots.ToArray(), whereClause, new List (), DuplicateElimination.No, joinTreeRoot) { } // effects: Given all the fields, just sets them. private CellQuery(SchemaContext schemaContext, ProjectedSlot[] projectedSlots, BoolExpression whereClause, List boolExprs, DuplicateElimination elimDupl, ExtentJoinTreeNode joinTreeRoot) { m_schemaContext = schemaContext; m_boolExprs = boolExprs; m_projectedSlots = projectedSlots; m_whereClause = whereClause; m_originalWhereClause = whereClause; m_eliminateDuplicates = elimDupl; m_joinTreeRoot = joinTreeRoot; } /// /// Copy Constructor /// internal CellQuery(CellQuery source) { this.m_basicCellRelation = source.m_basicCellRelation; this.m_boolExprs = source.m_boolExprs; this.m_eliminateDuplicates = source.m_eliminateDuplicates; this.m_joinTreeRoot = source.m_joinTreeRoot; this.m_originalWhereClause = source.m_originalWhereClause; this.m_projectedSlots = source.m_projectedSlots; this.m_schemaContext = source.m_schemaContext; 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(existing.m_schemaContext, newSlots, existing.m_whereClause, existing.m_boolExprs, existing.m_eliminateDuplicates, existing.m_joinTreeRoot) { } #endregion #region Fields // Whether query has a 'SELECT DISTINCT' on top private enum DuplicateElimination { Yes, No } // A reference to the schema information private SchemaContext m_schemaContext; // The boolean expressions that essentially capture the type information // Fixed-size list; NULL in the list means 'unused' private Listm_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; // This is the where clause created when the constructor was called // i.e., when FixCellConstantDomains is called, this // m_originalWhereClause is not changed private BoolExpression m_originalWhereClause; private DuplicateElimination m_eliminateDuplicates; // The from part of the query private ExtentJoinTreeNode m_joinTreeRoot; // The basic cell relation for all slots in this private BasicCellRelation m_basicCellRelation; #endregion #region Properties // effects: Returns the top levelextent corresponding to this cell query internal EntitySetBase Extent { // CHANGE_[....]_FEATURE_COMPOSITION What happens with composition get { EntitySetBase extent = m_joinTreeRoot.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; } } // effects: Returns the number of boolean expressions projected in the query internal int NumBoolVars { get { return m_boolExprs.Count; } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal BoolExpression OriginalWhereClause { get { return m_originalWhereClause; } } internal BoolExpression WhereClause { get { return m_whereClause; } } // effects: Returns the root of the join tree internal JoinTreeNode JoinTreeRoot { get { return m_joinTreeRoot; } } // 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; } } #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 (JoinTreeSlot.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]; JoinTreeSlot slot = projectedSlot as JoinTreeSlot; 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 (JoinTreeSlot 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 JoinTreeSlot cSlot = (JoinTreeSlot)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 JoinTreeSlot slot0 = (JoinTreeSlot) m_projectedSlots[cSideSlotIndexes[0]]; JoinTreeSlot slot1 = (JoinTreeSlot) 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) { StringBuilder builder = new StringBuilder(); bool foundError = false; foreach (OneOfConst oneOfConst in GetConjunctsFromOriginalWhereClause()) { if (oneOfConst.Values.ContainsNotNull()) { JoinTreeSlot slot = JoinTreeSlot.GetSlotForMember(m_projectedSlots, oneOfConst.Slot.MemberPath); if (slot == null) { // condition of NotNull and slot not being projected builder.AppendLine(System.Data.Entity.Strings.ViewGen_NotNull_No_Projected_Slot_0( oneOfConst.Slot.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, ConstantSlot 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, MemberPathMapBase 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++) { JoinTreeSlot slot = m_projectedSlots[i] as JoinTreeSlot; 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) { JoinTreeSlot projectedVar = projectedSlot as JoinTreeSlot; 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
- XmlSchemaType.cs
- RangeContentEnumerator.cs
- SaveFileDialog.cs
- SQLInt64Storage.cs
- StringDictionaryCodeDomSerializer.cs
- ArrayExtension.cs
- SafeHandles.cs
- MetadataProperty.cs
- DiffuseMaterial.cs
- CornerRadiusConverter.cs
- HostedElements.cs
- SmiEventSink_Default.cs
- MemberDomainMap.cs
- CustomWebEventKey.cs
- TreeNodeBinding.cs
- QilSortKey.cs
- WizardStepBase.cs
- ProfilePropertyMetadata.cs
- OpenFileDialog.cs
- ManagementClass.cs
- EventProvider.cs
- MemberExpression.cs
- TextEditorLists.cs
- MatrixTransform3D.cs
- ConfigXmlWhitespace.cs
- AspNetSynchronizationContext.cs
- HtmlInputSubmit.cs
- ExtensibleClassFactory.cs
- XmlDigitalSignatureProcessor.cs
- XmlSigningNodeWriter.cs
- JsonObjectDataContract.cs
- ConnectionManagementElementCollection.cs
- VariableQuery.cs
- ConfigurationElement.cs
- ParameterReplacerVisitor.cs
- CrossSiteScriptingValidation.cs
- NameValueCollection.cs
- UIInitializationException.cs
- Exceptions.cs
- LineInfo.cs
- QuestionEventArgs.cs
- ISFTagAndGuidCache.cs
- diagnosticsswitches.cs
- CallTemplateAction.cs
- TextRunCacheImp.cs
- WindowsGraphicsCacheManager.cs
- EncoderFallback.cs
- SHA1Cng.cs
- Msec.cs
- Brush.cs
- AssemblyNameProxy.cs
- SurrogateSelector.cs
- BindingList.cs
- OlePropertyStructs.cs
- TeredoHelper.cs
- XmlNodeList.cs
- PerformanceCounter.cs
- SrgsElement.cs
- ColorConverter.cs
- RawStylusSystemGestureInputReport.cs
- PromptBuilder.cs
- SplayTreeNode.cs
- ControlBuilder.cs
- DrawingAttributes.cs
- WebContext.cs
- SamlSubjectStatement.cs
- SystemIcmpV6Statistics.cs
- MLangCodePageEncoding.cs
- Base64Decoder.cs
- PropertyNames.cs
- EditorPartDesigner.cs
- ToolBarButtonClickEvent.cs
- Memoizer.cs
- GeneralTransformGroup.cs
- Repeater.cs
- InvokeGenerator.cs
- ExportOptions.cs
- CompilerGlobalScopeAttribute.cs
- PartialCachingControl.cs
- RichTextBox.cs
- EventKeyword.cs
- TreeNodeClickEventArgs.cs
- SEHException.cs
- RecommendedAsConfigurableAttribute.cs
- ImpersonationContext.cs
- TextTreeTextElementNode.cs
- MultipartIdentifier.cs
- DispatcherTimer.cs
- MultiByteCodec.cs
- GridViewColumnHeader.cs
- WebPart.cs
- TextTreeUndo.cs
- MessageDecoder.cs
- TouchEventArgs.cs
- EntityParameterCollection.cs
- HttpListener.cs
- ProtectedConfigurationSection.cs
- NativeMethods.cs
- CustomValidator.cs
- SizeFConverter.cs