Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / LeftCellWrapper.cs / 3 / LeftCellWrapper.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.Common.Utils; using System.Text; using System.Linq; using System.Diagnostics; using System.Collections.ObjectModel; using System.Data.Metadata.Edm; using System.Data.Common.Utils.Boolean; using System.Data.Mapping.ViewGeneration.Validation; using System.Data.Mapping.ViewGeneration.QueryRewriting; namespace System.Data.Mapping.ViewGeneration.Structures { // This class essentially stores a cell but in a special form. When we // are generating a view for an extent, we denote the extent's side (C or // S) as the "left side" and the side being used in the view as the right // side. For example, in query views, the C side is the left side. // // Each LeftCellWrapper is a cell of the form: // Project[A1,...,An] (Select[var IN {domain}] (Extent)) = Expr // Where // - "domain" is a set of multiconstants that correspond to the different // variable values allowed for the cell query // - A1 ... An are denoted by Attributes in this and corresponds to // the list of attributes that are projected // - Extent is the extent for which th view is being generated // - Expr is the expression on the other side to produce the left side of // the cell internal class LeftCellWrapper : InternalBase { #region Constructor // effects: Creates a LeftCellWrapper of the form: // Project[attrs] (Select[var IN {domain}] (Extent)) = cellquery // memberMaps is the set of maps used for producing the query or update views internal LeftCellWrapper(SchemaContext schemaContext, Setattrs, FragmentQuery fragmentQuery, CellQuery cellQuery, MemberMaps memberMaps, IEnumerable inputCells) { m_fragmentQuery = fragmentQuery; m_rightCellQuery = cellQuery; m_attributes = attrs; m_schemaContext = schemaContext; m_memberMaps = memberMaps; m_cells = new HashSet | (inputCells); } internal LeftCellWrapper(SchemaContext schemaContext, Set | attrs, FragmentQuery fragmentQuery, CellQuery cellQuery, MemberMaps memberMaps, Cell inputCell) : this(schemaContext, attrs, fragmentQuery, cellQuery, memberMaps, new Cell[] { inputCell }) { } #endregion #region Fields internal static readonly IEqualityComparer BoolEqualityComparer = new BoolWrapperComparer(); private Set m_attributes;// project: attributes computed by // Expr (projected attributes that get set) private MemberMaps m_memberMaps; private CellQuery m_rightCellQuery; // expression that computes this portion private HashSet m_cells; private SchemaContext m_schemaContext; private FragmentQuery m_fragmentQuery; // fragment query corresponding to the left cell query of the cell internal static readonly IComparer | Comparer = new LeftCellWrapperComparer(); internal static readonly IComparer OriginalCellIdComparer = new CellIdComparer(); #endregion #region Properties internal FragmentQuery FragmentQuery { get { return m_fragmentQuery; } } internal SchemaContext SchemaContext { get { return m_schemaContext;} } // effects: Returns the projected fields on the left side internal Set Attributes { get { return m_attributes; } } // effects: Returns the original cell number from which the wrapper came internal string OriginalCellNumberString { get { return StringUtil.ToSeparatedString(m_cells.Select(cell => cell.CellNumberAsString), "+", ""); } } // effects: Returns the right domain map associated with the right query internal MemberDomainMap RightDomainMap { get { return m_memberMaps.RightDomainMap; } } [Conditional("DEBUG")] internal void AssertHasUniqueCell() { Debug.Assert(m_cells.Count == 1); } internal IEnumerable Cells { get { return m_cells; } } // requires: There is only one input cell in this // effects: Returns the input cell provided to view generation as part of the mapping internal Cell OnlyInputCell { get { AssertHasUniqueCell(); return m_cells.First(); } } // effects: Returns the right CellQuery internal CellQuery RightCellQuery { get { return m_rightCellQuery; } } // effects: Returns the extent for which the wrapper was built internal EntitySetBase LeftExtent { get { return m_cells.First().GetLeftQuery(m_schemaContext.ViewTarget).Extent; } } // effects: Returns the extent of the right cellquery internal EntitySetBase RightExtent { get { EntitySetBase result = m_rightCellQuery.Extent; Debug.Assert(result != null, "Bad root value in join tree"); return result; } } #endregion #region Methods // effects: Yields the input cells in wrappers internal static IEnumerable | GetInputCellsForWrappers(IEnumerable | wrappers) { foreach (LeftCellWrapper wrapper in wrappers) { foreach (Cell cell in wrapper.m_cells) { yield return cell; } } } // requires: RightCellQuery.Extent corresponds to a relationship set // effects: Returns the ends to which the key of the corresponding // table (i.e., the left query) maps to in the relationship set. For // example, if RightCellQuery.Extent is OrderOrders and it maps to // of table SOrders with key oid, this returns the // end to which oid is mapped. Similarly, if we have a link table // with the whole key mapped to two ends of the association set, it // returns both ends private Set GetEndsForTablePrimaryKey() { CellQuery rightQuery = RightCellQuery; Set result = new Set (EqualityComparer .Default); // Get the key slots for the table (they are in the slotMap) and // check for that slot on the C-side foreach (int keySlot in m_memberMaps.ProjectedSlotMap.KeySlots) { JoinTreeSlot slot = (JoinTreeSlot)rightQuery.ProjectedSlotAt(keySlot); MemberPath path = slot.MemberPath; // See what end it maps to in the relationSet AssociationEndMember endMember = (AssociationEndMember)path.FirstMember; Debug.Assert(endMember != null, "Element in path before scalar path is not end property?"); result.Add(endMember); } Debug.Assert(result != null, "No end found for keyslots of table?"); return result; } // effects: Creates a boolean variable representing the right extent or association end internal RoleBoolean CreateRoleBoolean() { if (RightExtent is AssociationSet) { Set ends = GetEndsForTablePrimaryKey(); if (ends.Count == 1) { AssociationSetEnd setEnd = ((AssociationSet)RightExtent).AssociationSetEnds[ends.First().Name]; return new RoleBoolean(setEnd); } } return new RoleBoolean(RightExtent); } // effects: Given a set of wrappers, returns a string that contains the list of extents in the // rightcellQueries of the wrappers internal static string GetExtentListAsUserString(IEnumerable wrappers) { Set extents = new Set (EqualityComparer .Default); foreach (LeftCellWrapper wrapper in wrappers) { extents.Add(wrapper.RightExtent); } StringBuilder builder = new StringBuilder(); bool isFirst = true; foreach (EntitySetBase extent in extents) { if (isFirst == false) { builder.Append(", "); } isFirst = false; builder.Append(extent.Name); } return builder.ToString(); } internal override void ToFullString(StringBuilder builder) { builder.Append("P["); StringUtil.ToSeparatedString(builder, m_attributes, ","); builder.Append("] = "); m_rightCellQuery.ToFullString(builder); } // effects: Modifies stringBuilder to contain the view corresponding // to the right cellquery internal override void ToCompactString(StringBuilder stringBuilder) { stringBuilder.Append(OriginalCellNumberString); } // effects: Writes m_cellWrappers to builder internal static void WrappersToStringBuilder(StringBuilder builder, List wrappers, string header) { builder.AppendLine() .Append(header) .AppendLine(); // Sort them according to the original cell number LeftCellWrapper[] cellWrappers = wrappers.ToArray(); Array.Sort(cellWrappers, LeftCellWrapper.OriginalCellIdComparer); foreach (LeftCellWrapper wrapper in cellWrappers) { wrapper.ToCompactString(builder); builder.Append(" = "); wrapper.ToFullString(builder); builder.AppendLine(); } } #endregion #region Equality Comparer class // This class compares wrappers based on the Right Where Clause and // Extent -- needed for the boolean engine private class BoolWrapperComparer : IEqualityComparer { public bool Equals(LeftCellWrapper left, LeftCellWrapper 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 bool whereClauseEqual = BoolExpression.EqualityComparer.Equals(left.RightCellQuery.WhereClause, right.RightCellQuery.WhereClause); return left.RightExtent.Equals(right.RightExtent) && whereClauseEqual; } public int GetHashCode(LeftCellWrapper wrapper) { return BoolExpression.EqualityComparer.GetHashCode(wrapper.RightCellQuery.WhereClause) ^ wrapper.RightExtent.GetHashCode(); } } #endregion #region Comparer // A class that compares two cell wrappers. Useful for guiding heuristics // and to ensure that the largest selection domain (i.e., the number of // multiconstants in "mc in {...}") is first in the list private class LeftCellWrapperComparer : IComparer { public int Compare(LeftCellWrapper x, LeftCellWrapper y) { // More attributes first -- so that we get most attributes // with very few intersections (when we use the sortings for // that). When we are subtracting, attributes are not important // Use FragmentQuery's attributes instead of LeftCellWrapper's original attributes in the comparison // since the former might have got extended to include all attributes whose value is determined // by the WHERE clause (e.g., if we have WHERE ProductName='Camera' we can assume ProductName is projected) if (x.FragmentQuery.Attributes.Count > y.FragmentQuery.Attributes.Count) { return -1; } else if (x.FragmentQuery.Attributes.Count < y.FragmentQuery.Attributes.Count) { return 1; } // Since the sort may not be stable, we use the original cell number string to break the tie return String.CompareOrdinal(x.OriginalCellNumberString, y.OriginalCellNumberString); } } // A class that compares two cell wrappers based on original cell number internal class CellIdComparer : IComparer { public int Compare(LeftCellWrapper x, LeftCellWrapper y) { return StringComparer.Ordinal.Compare(x.OriginalCellNumberString, y.OriginalCellNumberString); } } #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.Text; using System.Linq; using System.Diagnostics; using System.Collections.ObjectModel; using System.Data.Metadata.Edm; using System.Data.Common.Utils.Boolean; using System.Data.Mapping.ViewGeneration.Validation; using System.Data.Mapping.ViewGeneration.QueryRewriting; namespace System.Data.Mapping.ViewGeneration.Structures { // This class essentially stores a cell but in a special form. When we // are generating a view for an extent, we denote the extent's side (C or // S) as the "left side" and the side being used in the view as the right // side. For example, in query views, the C side is the left side. // // Each LeftCellWrapper is a cell of the form: // Project[A1,...,An] (Select[var IN {domain}] (Extent)) = Expr // Where // - "domain" is a set of multiconstants that correspond to the different // variable values allowed for the cell query // - A1 ... An are denoted by Attributes in this and corresponds to // the list of attributes that are projected // - Extent is the extent for which th view is being generated // - Expr is the expression on the other side to produce the left side of // the cell internal class LeftCellWrapper : InternalBase { #region Constructor // effects: Creates a LeftCellWrapper of the form: // Project[attrs] (Select[var IN {domain}] (Extent)) = cellquery // memberMaps is the set of maps used for producing the query or update views internal LeftCellWrapper(SchemaContext schemaContext, Setattrs, FragmentQuery fragmentQuery, CellQuery cellQuery, MemberMaps memberMaps, IEnumerable inputCells) { m_fragmentQuery = fragmentQuery; m_rightCellQuery = cellQuery; m_attributes = attrs; m_schemaContext = schemaContext; m_memberMaps = memberMaps; m_cells = new HashSet | (inputCells); } internal LeftCellWrapper(SchemaContext schemaContext, Set | attrs, FragmentQuery fragmentQuery, CellQuery cellQuery, MemberMaps memberMaps, Cell inputCell) : this(schemaContext, attrs, fragmentQuery, cellQuery, memberMaps, new Cell[] { inputCell }) { } #endregion #region Fields internal static readonly IEqualityComparer BoolEqualityComparer = new BoolWrapperComparer(); private Set m_attributes;// project: attributes computed by // Expr (projected attributes that get set) private MemberMaps m_memberMaps; private CellQuery m_rightCellQuery; // expression that computes this portion private HashSet m_cells; private SchemaContext m_schemaContext; private FragmentQuery m_fragmentQuery; // fragment query corresponding to the left cell query of the cell internal static readonly IComparer | Comparer = new LeftCellWrapperComparer(); internal static readonly IComparer OriginalCellIdComparer = new CellIdComparer(); #endregion #region Properties internal FragmentQuery FragmentQuery { get { return m_fragmentQuery; } } internal SchemaContext SchemaContext { get { return m_schemaContext;} } // effects: Returns the projected fields on the left side internal Set Attributes { get { return m_attributes; } } // effects: Returns the original cell number from which the wrapper came internal string OriginalCellNumberString { get { return StringUtil.ToSeparatedString(m_cells.Select(cell => cell.CellNumberAsString), "+", ""); } } // effects: Returns the right domain map associated with the right query internal MemberDomainMap RightDomainMap { get { return m_memberMaps.RightDomainMap; } } [Conditional("DEBUG")] internal void AssertHasUniqueCell() { Debug.Assert(m_cells.Count == 1); } internal IEnumerable Cells { get { return m_cells; } } // requires: There is only one input cell in this // effects: Returns the input cell provided to view generation as part of the mapping internal Cell OnlyInputCell { get { AssertHasUniqueCell(); return m_cells.First(); } } // effects: Returns the right CellQuery internal CellQuery RightCellQuery { get { return m_rightCellQuery; } } // effects: Returns the extent for which the wrapper was built internal EntitySetBase LeftExtent { get { return m_cells.First().GetLeftQuery(m_schemaContext.ViewTarget).Extent; } } // effects: Returns the extent of the right cellquery internal EntitySetBase RightExtent { get { EntitySetBase result = m_rightCellQuery.Extent; Debug.Assert(result != null, "Bad root value in join tree"); return result; } } #endregion #region Methods // effects: Yields the input cells in wrappers internal static IEnumerable | GetInputCellsForWrappers(IEnumerable | wrappers) { foreach (LeftCellWrapper wrapper in wrappers) { foreach (Cell cell in wrapper.m_cells) { yield return cell; } } } // requires: RightCellQuery.Extent corresponds to a relationship set // effects: Returns the ends to which the key of the corresponding // table (i.e., the left query) maps to in the relationship set. For // example, if RightCellQuery.Extent is OrderOrders and it maps to // of table SOrders with key oid, this returns the // end to which oid is mapped. Similarly, if we have a link table // with the whole key mapped to two ends of the association set, it // returns both ends private Set GetEndsForTablePrimaryKey() { CellQuery rightQuery = RightCellQuery; Set result = new Set (EqualityComparer .Default); // Get the key slots for the table (they are in the slotMap) and // check for that slot on the C-side foreach (int keySlot in m_memberMaps.ProjectedSlotMap.KeySlots) { JoinTreeSlot slot = (JoinTreeSlot)rightQuery.ProjectedSlotAt(keySlot); MemberPath path = slot.MemberPath; // See what end it maps to in the relationSet AssociationEndMember endMember = (AssociationEndMember)path.FirstMember; Debug.Assert(endMember != null, "Element in path before scalar path is not end property?"); result.Add(endMember); } Debug.Assert(result != null, "No end found for keyslots of table?"); return result; } // effects: Creates a boolean variable representing the right extent or association end internal RoleBoolean CreateRoleBoolean() { if (RightExtent is AssociationSet) { Set ends = GetEndsForTablePrimaryKey(); if (ends.Count == 1) { AssociationSetEnd setEnd = ((AssociationSet)RightExtent).AssociationSetEnds[ends.First().Name]; return new RoleBoolean(setEnd); } } return new RoleBoolean(RightExtent); } // effects: Given a set of wrappers, returns a string that contains the list of extents in the // rightcellQueries of the wrappers internal static string GetExtentListAsUserString(IEnumerable wrappers) { Set extents = new Set (EqualityComparer .Default); foreach (LeftCellWrapper wrapper in wrappers) { extents.Add(wrapper.RightExtent); } StringBuilder builder = new StringBuilder(); bool isFirst = true; foreach (EntitySetBase extent in extents) { if (isFirst == false) { builder.Append(", "); } isFirst = false; builder.Append(extent.Name); } return builder.ToString(); } internal override void ToFullString(StringBuilder builder) { builder.Append("P["); StringUtil.ToSeparatedString(builder, m_attributes, ","); builder.Append("] = "); m_rightCellQuery.ToFullString(builder); } // effects: Modifies stringBuilder to contain the view corresponding // to the right cellquery internal override void ToCompactString(StringBuilder stringBuilder) { stringBuilder.Append(OriginalCellNumberString); } // effects: Writes m_cellWrappers to builder internal static void WrappersToStringBuilder(StringBuilder builder, List wrappers, string header) { builder.AppendLine() .Append(header) .AppendLine(); // Sort them according to the original cell number LeftCellWrapper[] cellWrappers = wrappers.ToArray(); Array.Sort(cellWrappers, LeftCellWrapper.OriginalCellIdComparer); foreach (LeftCellWrapper wrapper in cellWrappers) { wrapper.ToCompactString(builder); builder.Append(" = "); wrapper.ToFullString(builder); builder.AppendLine(); } } #endregion #region Equality Comparer class // This class compares wrappers based on the Right Where Clause and // Extent -- needed for the boolean engine private class BoolWrapperComparer : IEqualityComparer { public bool Equals(LeftCellWrapper left, LeftCellWrapper 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 bool whereClauseEqual = BoolExpression.EqualityComparer.Equals(left.RightCellQuery.WhereClause, right.RightCellQuery.WhereClause); return left.RightExtent.Equals(right.RightExtent) && whereClauseEqual; } public int GetHashCode(LeftCellWrapper wrapper) { return BoolExpression.EqualityComparer.GetHashCode(wrapper.RightCellQuery.WhereClause) ^ wrapper.RightExtent.GetHashCode(); } } #endregion #region Comparer // A class that compares two cell wrappers. Useful for guiding heuristics // and to ensure that the largest selection domain (i.e., the number of // multiconstants in "mc in {...}") is first in the list private class LeftCellWrapperComparer : IComparer { public int Compare(LeftCellWrapper x, LeftCellWrapper y) { // More attributes first -- so that we get most attributes // with very few intersections (when we use the sortings for // that). When we are subtracting, attributes are not important // Use FragmentQuery's attributes instead of LeftCellWrapper's original attributes in the comparison // since the former might have got extended to include all attributes whose value is determined // by the WHERE clause (e.g., if we have WHERE ProductName='Camera' we can assume ProductName is projected) if (x.FragmentQuery.Attributes.Count > y.FragmentQuery.Attributes.Count) { return -1; } else if (x.FragmentQuery.Attributes.Count < y.FragmentQuery.Attributes.Count) { return 1; } // Since the sort may not be stable, we use the original cell number string to break the tie return String.CompareOrdinal(x.OriginalCellNumberString, y.OriginalCellNumberString); } } // A class that compares two cell wrappers based on original cell number internal class CellIdComparer : IComparer { public int Compare(LeftCellWrapper x, LeftCellWrapper y) { return StringComparer.Ordinal.Compare(x.OriginalCellNumberString, y.OriginalCellNumberString); } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SByteConverter.cs
- DesignSurface.cs
- MaterialCollection.cs
- TabletDevice.cs
- CollectionType.cs
- PageOrientation.cs
- ObjectViewListener.cs
- Vector3DConverter.cs
- Utils.cs
- ValueProviderWrapper.cs
- UshortList2.cs
- SmtpNetworkElement.cs
- StreamingContext.cs
- XmlBoundElement.cs
- VersionedStreamOwner.cs
- CurrentChangedEventManager.cs
- OutputCacheProfile.cs
- ModelItemCollection.cs
- ToolBarButtonClickEvent.cs
- TypeConverterAttribute.cs
- DbCommandDefinition.cs
- MenuBindingsEditorForm.cs
- RecognizerStateChangedEventArgs.cs
- DesignerLoader.cs
- MenuItemCollectionEditor.cs
- ColorContextHelper.cs
- DbLambda.cs
- MarkerProperties.cs
- StyleModeStack.cs
- BuildProviderInstallComponent.cs
- ErrorHandler.cs
- WebPartManager.cs
- IncrementalReadDecoders.cs
- LocalValueEnumerator.cs
- CodeObject.cs
- HtmlControl.cs
- ToolStripGripRenderEventArgs.cs
- AesManaged.cs
- XPathDescendantIterator.cs
- HtmlHead.cs
- SmtpReplyReader.cs
- SystemUdpStatistics.cs
- DecimalFormatter.cs
- Boolean.cs
- WebPartCloseVerb.cs
- TableAdapterManagerHelper.cs
- _BaseOverlappedAsyncResult.cs
- DoubleAnimationUsingPath.cs
- FormsAuthenticationConfiguration.cs
- XmlElementAttributes.cs
- JulianCalendar.cs
- StreamInfo.cs
- SchemaMapping.cs
- EntityDataReader.cs
- PageCatalogPartDesigner.cs
- MediaTimeline.cs
- PlanCompiler.cs
- OLEDB_Enum.cs
- SiteMapDataSource.cs
- DataSourceCacheDurationConverter.cs
- SafeNativeMethods.cs
- XmlSchemaChoice.cs
- XamlSerializerUtil.cs
- AnnotationObservableCollection.cs
- AuthenticationSchemesHelper.cs
- PartialTrustHelpers.cs
- EmptyControlCollection.cs
- Schema.cs
- SafeNativeMethods.cs
- HttpServerVarsCollection.cs
- OleDbRowUpdatingEvent.cs
- ISCIIEncoding.cs
- SQLCharsStorage.cs
- SubMenuStyle.cs
- DesignRelationCollection.cs
- ToolboxDataAttribute.cs
- SqlProviderUtilities.cs
- BitmapEffectDrawingContent.cs
- WebBaseEventKeyComparer.cs
- PrintDialogException.cs
- DesignBindingEditor.cs
- DateTimeAutomationPeer.cs
- QuaternionRotation3D.cs
- ElementHost.cs
- CounterCreationDataConverter.cs
- DataGridViewRowPostPaintEventArgs.cs
- IndexOutOfRangeException.cs
- Convert.cs
- BasePropertyDescriptor.cs
- QueryGenerator.cs
- GenerateTemporaryTargetAssembly.cs
- Effect.cs
- ReceiveContent.cs
- PkcsUtils.cs
- BamlBinaryReader.cs
- Math.cs
- AsyncOperation.cs
- GridViewRowCollection.cs
- IdleTimeoutMonitor.cs
- HostingEnvironment.cs