Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / CellQuery.cs / 3 / 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 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;
// 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
- SoapIgnoreAttribute.cs
- DataRecord.cs
- arc.cs
- ObjectSet.cs
- EntityParameter.cs
- precedingsibling.cs
- FixedStringLookup.cs
- RealizationDrawingContextWalker.cs
- TreeNodeSelectionProcessor.cs
- PersistenceTypeAttribute.cs
- OutputScope.cs
- CompositeCollectionView.cs
- EntityDataSourceColumn.cs
- InputLanguageCollection.cs
- XPathCompileException.cs
- SqlMethodCallConverter.cs
- SqlCacheDependencySection.cs
- NameNode.cs
- FocusManager.cs
- EventMappingSettingsCollection.cs
- DataFieldEditor.cs
- RoutedPropertyChangedEventArgs.cs
- PageOutputColor.cs
- ConnectorMovedEventArgs.cs
- EventBuilder.cs
- DesignerDataParameter.cs
- CngKeyBlobFormat.cs
- CompensateDesigner.cs
- BoundsDrawingContextWalker.cs
- Int16Converter.cs
- HttpApplication.cs
- XslException.cs
- StreamHelper.cs
- DnsPermission.cs
- HtmlTitle.cs
- DataServiceQueryException.cs
- Button.cs
- QuaternionConverter.cs
- XmlSignificantWhitespace.cs
- WindowsGraphicsCacheManager.cs
- ObjectContext.cs
- HitTestWithGeometryDrawingContextWalker.cs
- BitmapEffectInputData.cs
- SafeTokenHandle.cs
- FileInfo.cs
- Metadata.cs
- ResolveDuplex11AsyncResult.cs
- BoundPropertyEntry.cs
- Authorization.cs
- DesignSurface.cs
- LayoutTableCell.cs
- EventTrigger.cs
- AdapterUtil.cs
- _NetworkingPerfCounters.cs
- SchemaConstraints.cs
- TextBreakpoint.cs
- PatternMatcher.cs
- ComponentCodeDomSerializer.cs
- SafeBuffer.cs
- XPathNode.cs
- XmlHierarchicalDataSourceView.cs
- NavigatorInvalidBodyAccessException.cs
- Tile.cs
- CodeDirectionExpression.cs
- BreadCrumbTextConverter.cs
- DemultiplexingDispatchMessageFormatter.cs
- BCLDebug.cs
- PropertyEntry.cs
- InvocationExpression.cs
- EntryIndex.cs
- IncrementalHitTester.cs
- TemplateInstanceAttribute.cs
- Typeface.cs
- DateTimeStorage.cs
- ResXFileRef.cs
- NativeObjectSecurity.cs
- Subtree.cs
- TextTreeText.cs
- Ref.cs
- DataGridAddNewRow.cs
- EventItfInfo.cs
- IntSecurity.cs
- Logging.cs
- FrameworkReadOnlyPropertyMetadata.cs
- CultureTableRecord.cs
- ColumnMapVisitor.cs
- SafeSystemMetrics.cs
- DataServiceOperationContext.cs
- AddressHeaderCollectionElement.cs
- Environment.cs
- StdRegProviderWrapper.cs
- KerberosSecurityTokenProvider.cs
- InternalCache.cs
- DefaultProxySection.cs
- SystemIPGlobalStatistics.cs
- StatusBarItemAutomationPeer.cs
- GregorianCalendarHelper.cs
- DPAPIProtectedConfigurationProvider.cs
- ColorDialog.cs
- CompareInfo.cs