Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Query / PlanCompiler / ConstraintManager.cs / 1305376 / ConstraintManager.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Data.Common;
using System.Data.Query.InternalTrees;
using md=System.Data.Metadata.Edm;
//using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class...
//
// The ConstraintManager module manages foreign key constraints for a query. It reshapes
// referential constraints supplied by metadata into a more useful form.
//
namespace System.Data.Query.PlanCompiler
{
///
/// A simple class that represents a pair of extents
///
internal class ExtentPair
{
#region public surface
///
/// Return the left component of the pair
///
internal md.EntitySetBase Left { get { return m_left; } }
///
/// Return the right component of the pair
///
internal md.EntitySetBase Right { get { return m_right; } }
///
/// Equals
///
///
///
public override bool Equals(object obj)
{
ExtentPair other = obj as ExtentPair;
return (other != null) && other.Left.Equals(this.Left) && other.Right.Equals(this.Right);
}
///
/// Hashcode
///
///
public override int GetHashCode()
{
return (this.Left.GetHashCode() << 4) ^ this.Right.GetHashCode();
}
#endregion
#region constructors
internal ExtentPair(md.EntitySetBase left, md.EntitySetBase right)
{
m_left = left;
m_right = right;
}
#endregion
#region private state
private md.EntitySetBase m_left;
private md.EntitySetBase m_right;
#endregion
}
///
/// Information about a foreign-key constraint
///
internal class ForeignKeyConstraint
{
#region public surface
///
/// Parent key properties
///
internal List ParentKeys { get { return m_parentKeys; } }
///
/// Child key properties
///
internal List ChildKeys { get { return m_childKeys; } }
///
/// Get the parent-child pair
///
internal ExtentPair Pair { get { return m_extentPair; } }
///
/// Return the child rowcount
///
internal md.RelationshipMultiplicity ChildMultiplicity { get { return m_constraint.ToRole.RelationshipMultiplicity; } }
///
/// Get the corresponding parent (key) property, for a specific child (foreign key) property
///
/// child (foreign key) property name
/// corresponding parent property name
/// true, if the parent property was found
internal bool GetParentProperty(string childPropertyName, out string parentPropertyName)
{
BuildKeyMap();
return m_keyMap.TryGetValue(childPropertyName, out parentPropertyName);
}
#endregion
#region constructors
internal ForeignKeyConstraint(md.RelationshipType relType, md.RelationshipSet relationshipSet, md.ReferentialConstraint constraint)
{
md.AssociationSet assocSet = relationshipSet as md.AssociationSet;
md.AssociationEndMember fromEnd = constraint.FromRole as md.AssociationEndMember;
md.AssociationEndMember toEnd = constraint.ToRole as md.AssociationEndMember;
// Currently only Associations are supported
if (null == assocSet || null == fromEnd || null == toEnd)
{
throw EntityUtil.NotSupported();
}
m_constraint = constraint;
md.EntitySet parent = System.Data.Common.Utils.MetadataHelper.GetEntitySetAtEnd(assocSet, fromEnd);// relationshipSet.GetRelationshipEndExtent(constraint.FromRole);
md.EntitySet child = System.Data.Common.Utils.MetadataHelper.GetEntitySetAtEnd(assocSet, toEnd);// relationshipSet.GetRelationshipEndExtent(constraint.ToRole);
m_extentPair = new ExtentPair(parent, child);
m_childKeys = new List();
foreach (md.EdmProperty prop in constraint.ToProperties)
{
m_childKeys.Add(prop.Name);
}
m_parentKeys = new List();
foreach (md.EdmProperty prop in constraint.FromProperties)
{
m_parentKeys.Add(prop.Name);
}
PlanCompiler.Assert((md.RelationshipMultiplicity.ZeroOrOne == fromEnd.RelationshipMultiplicity || md.RelationshipMultiplicity.One == fromEnd.RelationshipMultiplicity), "from-end of relationship constraint cannot have multiplicity greater than 1");
}
#endregion
#region private state
private ExtentPair m_extentPair;
private List m_parentKeys;
private List m_childKeys;
private md.ReferentialConstraint m_constraint;
private Dictionary m_keyMap;
#endregion
#region private methods
///
/// Build up an equivalence map of primary keys and foreign keys (ie) for each
/// foreign key column, identify the corresponding primary key property
///
private void BuildKeyMap()
{
if (m_keyMap != null)
{
return;
}
m_keyMap = new Dictionary();
IEnumerator parentProps = m_constraint.FromProperties.GetEnumerator();
IEnumerator childProps = m_constraint.ToProperties.GetEnumerator();
while (true)
{
bool parentOver = !parentProps.MoveNext();
bool childOver = !childProps.MoveNext();
PlanCompiler.Assert(parentOver == childOver, "key count mismatch");
if (parentOver)
{
break;
}
m_keyMap[childProps.Current.Name] = parentProps.Current.Name;
}
}
#endregion
}
///
/// Keeps track of all foreign key relationships
///
internal class ConstraintManager
{
#region public methods
///
/// Is there a parent child relationship between table1 and table2 ?
///
/// parent table ?
/// child table ?
/// list of constraints ?
/// true if there is at least one constraint
internal bool IsParentChildRelationship(md.EntitySetBase table1, md.EntitySetBase table2,
out List constraints)
{
LoadRelationships(table1.EntityContainer);
LoadRelationships(table2.EntityContainer);
ExtentPair extentPair = new ExtentPair(table1, table2);
return m_parentChildRelationships.TryGetValue(extentPair, out constraints);
}
///
/// Load all relationships in this entity container
///
///
internal void LoadRelationships(md.EntityContainer entityContainer)
{
// Check to see if I've already loaded information for this entity container
if (m_entityContainerMap.ContainsKey(entityContainer))
{
return;
}
// Load all relationships from this entitycontainer
foreach (md.EntitySetBase e in entityContainer.BaseEntitySets)
{
md.RelationshipSet relationshipSet = e as md.RelationshipSet;
if (relationshipSet == null)
{
continue;
}
// Relationship sets can only contain relationships
md.RelationshipType relationshipType = (md.RelationshipType)relationshipSet.ElementType;
md.AssociationType assocType = relationshipType as md.AssociationType;
//
// Handle only binary Association relationships for now
//
if (null == assocType || !IsBinary(relationshipType))
{
continue;
}
foreach (md.ReferentialConstraint constraint in assocType.ReferentialConstraints)
{
List fkConstraintList;
ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint(relationshipType, relationshipSet, constraint);
if (!m_parentChildRelationships.TryGetValue(fkConstraint.Pair, out fkConstraintList))
{
fkConstraintList = new List();
m_parentChildRelationships[fkConstraint.Pair] = fkConstraintList;
}
//
// Theoretically, we can have more than one fk constraint between
// the 2 tables (though, it is unlikely)
//
fkConstraintList.Add(fkConstraint);
}
}
// Mark this entity container as already loaded
m_entityContainerMap[entityContainer] = entityContainer;
}
#endregion
#region constructors
internal ConstraintManager()
{
m_entityContainerMap = new Dictionary();
m_parentChildRelationships = new Dictionary>();
}
#endregion
#region private state
private Dictionary m_entityContainerMap;
private Dictionary> m_parentChildRelationships;
#endregion
#region private methods
///
/// Is this relationship a binary relationship (ie) does it have exactly 2 end points?
///
/// This should ideally be a method supported by RelationType itself
///
///
/// true, if this is a binary relationship
private static bool IsBinary(md.RelationshipType relationshipType)
{
int endCount = 0;
foreach(md.EdmMember member in relationshipType.Members)
{
if (member is md.RelationshipEndMember)
{
endCount++;
if (endCount > 2)
{
return false;
}
}
}
return (endCount == 2);
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Data.Common;
using System.Data.Query.InternalTrees;
using md=System.Data.Metadata.Edm;
//using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class...
//
// The ConstraintManager module manages foreign key constraints for a query. It reshapes
// referential constraints supplied by metadata into a more useful form.
//
namespace System.Data.Query.PlanCompiler
{
///
/// A simple class that represents a pair of extents
///
internal class ExtentPair
{
#region public surface
///
/// Return the left component of the pair
///
internal md.EntitySetBase Left { get { return m_left; } }
///
/// Return the right component of the pair
///
internal md.EntitySetBase Right { get { return m_right; } }
///
/// Equals
///
///
///
public override bool Equals(object obj)
{
ExtentPair other = obj as ExtentPair;
return (other != null) && other.Left.Equals(this.Left) && other.Right.Equals(this.Right);
}
///
/// Hashcode
///
///
public override int GetHashCode()
{
return (this.Left.GetHashCode() << 4) ^ this.Right.GetHashCode();
}
#endregion
#region constructors
internal ExtentPair(md.EntitySetBase left, md.EntitySetBase right)
{
m_left = left;
m_right = right;
}
#endregion
#region private state
private md.EntitySetBase m_left;
private md.EntitySetBase m_right;
#endregion
}
///
/// Information about a foreign-key constraint
///
internal class ForeignKeyConstraint
{
#region public surface
///
/// Parent key properties
///
internal List ParentKeys { get { return m_parentKeys; } }
///
/// Child key properties
///
internal List ChildKeys { get { return m_childKeys; } }
///
/// Get the parent-child pair
///
internal ExtentPair Pair { get { return m_extentPair; } }
///
/// Return the child rowcount
///
internal md.RelationshipMultiplicity ChildMultiplicity { get { return m_constraint.ToRole.RelationshipMultiplicity; } }
///
/// Get the corresponding parent (key) property, for a specific child (foreign key) property
///
/// child (foreign key) property name
/// corresponding parent property name
/// true, if the parent property was found
internal bool GetParentProperty(string childPropertyName, out string parentPropertyName)
{
BuildKeyMap();
return m_keyMap.TryGetValue(childPropertyName, out parentPropertyName);
}
#endregion
#region constructors
internal ForeignKeyConstraint(md.RelationshipType relType, md.RelationshipSet relationshipSet, md.ReferentialConstraint constraint)
{
md.AssociationSet assocSet = relationshipSet as md.AssociationSet;
md.AssociationEndMember fromEnd = constraint.FromRole as md.AssociationEndMember;
md.AssociationEndMember toEnd = constraint.ToRole as md.AssociationEndMember;
// Currently only Associations are supported
if (null == assocSet || null == fromEnd || null == toEnd)
{
throw EntityUtil.NotSupported();
}
m_constraint = constraint;
md.EntitySet parent = System.Data.Common.Utils.MetadataHelper.GetEntitySetAtEnd(assocSet, fromEnd);// relationshipSet.GetRelationshipEndExtent(constraint.FromRole);
md.EntitySet child = System.Data.Common.Utils.MetadataHelper.GetEntitySetAtEnd(assocSet, toEnd);// relationshipSet.GetRelationshipEndExtent(constraint.ToRole);
m_extentPair = new ExtentPair(parent, child);
m_childKeys = new List();
foreach (md.EdmProperty prop in constraint.ToProperties)
{
m_childKeys.Add(prop.Name);
}
m_parentKeys = new List();
foreach (md.EdmProperty prop in constraint.FromProperties)
{
m_parentKeys.Add(prop.Name);
}
PlanCompiler.Assert((md.RelationshipMultiplicity.ZeroOrOne == fromEnd.RelationshipMultiplicity || md.RelationshipMultiplicity.One == fromEnd.RelationshipMultiplicity), "from-end of relationship constraint cannot have multiplicity greater than 1");
}
#endregion
#region private state
private ExtentPair m_extentPair;
private List m_parentKeys;
private List m_childKeys;
private md.ReferentialConstraint m_constraint;
private Dictionary m_keyMap;
#endregion
#region private methods
///
/// Build up an equivalence map of primary keys and foreign keys (ie) for each
/// foreign key column, identify the corresponding primary key property
///
private void BuildKeyMap()
{
if (m_keyMap != null)
{
return;
}
m_keyMap = new Dictionary();
IEnumerator parentProps = m_constraint.FromProperties.GetEnumerator();
IEnumerator childProps = m_constraint.ToProperties.GetEnumerator();
while (true)
{
bool parentOver = !parentProps.MoveNext();
bool childOver = !childProps.MoveNext();
PlanCompiler.Assert(parentOver == childOver, "key count mismatch");
if (parentOver)
{
break;
}
m_keyMap[childProps.Current.Name] = parentProps.Current.Name;
}
}
#endregion
}
///
/// Keeps track of all foreign key relationships
///
internal class ConstraintManager
{
#region public methods
///
/// Is there a parent child relationship between table1 and table2 ?
///
/// parent table ?
/// child table ?
/// list of constraints ?
/// true if there is at least one constraint
internal bool IsParentChildRelationship(md.EntitySetBase table1, md.EntitySetBase table2,
out List constraints)
{
LoadRelationships(table1.EntityContainer);
LoadRelationships(table2.EntityContainer);
ExtentPair extentPair = new ExtentPair(table1, table2);
return m_parentChildRelationships.TryGetValue(extentPair, out constraints);
}
///
/// Load all relationships in this entity container
///
///
internal void LoadRelationships(md.EntityContainer entityContainer)
{
// Check to see if I've already loaded information for this entity container
if (m_entityContainerMap.ContainsKey(entityContainer))
{
return;
}
// Load all relationships from this entitycontainer
foreach (md.EntitySetBase e in entityContainer.BaseEntitySets)
{
md.RelationshipSet relationshipSet = e as md.RelationshipSet;
if (relationshipSet == null)
{
continue;
}
// Relationship sets can only contain relationships
md.RelationshipType relationshipType = (md.RelationshipType)relationshipSet.ElementType;
md.AssociationType assocType = relationshipType as md.AssociationType;
//
// Handle only binary Association relationships for now
//
if (null == assocType || !IsBinary(relationshipType))
{
continue;
}
foreach (md.ReferentialConstraint constraint in assocType.ReferentialConstraints)
{
List fkConstraintList;
ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint(relationshipType, relationshipSet, constraint);
if (!m_parentChildRelationships.TryGetValue(fkConstraint.Pair, out fkConstraintList))
{
fkConstraintList = new List();
m_parentChildRelationships[fkConstraint.Pair] = fkConstraintList;
}
//
// Theoretically, we can have more than one fk constraint between
// the 2 tables (though, it is unlikely)
//
fkConstraintList.Add(fkConstraint);
}
}
// Mark this entity container as already loaded
m_entityContainerMap[entityContainer] = entityContainer;
}
#endregion
#region constructors
internal ConstraintManager()
{
m_entityContainerMap = new Dictionary();
m_parentChildRelationships = new Dictionary>();
}
#endregion
#region private state
private Dictionary m_entityContainerMap;
private Dictionary> m_parentChildRelationships;
#endregion
#region private methods
///
/// Is this relationship a binary relationship (ie) does it have exactly 2 end points?
///
/// This should ideally be a method supported by RelationType itself
///
///
/// true, if this is a binary relationship
private static bool IsBinary(md.RelationshipType relationshipType)
{
int endCount = 0;
foreach(md.EdmMember member in relationshipType.Members)
{
if (member is md.RelationshipEndMember)
{
endCount++;
if (endCount > 2)
{
return false;
}
}
}
return (endCount == 2);
}
#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
- GetIndexBinder.cs
- LocatorGroup.cs
- XmlCharCheckingReader.cs
- ColorPalette.cs
- ClosureBinding.cs
- MaskedTextBoxDesignerActionList.cs
- ApplicationServiceManager.cs
- BasicHttpMessageCredentialType.cs
- HostingEnvironment.cs
- HostedElements.cs
- StringPropertyBuilder.cs
- UpDownBase.cs
- DragEvent.cs
- datacache.cs
- OdbcConnectionPoolProviderInfo.cs
- MarkupExtensionSerializer.cs
- ExeConfigurationFileMap.cs
- UriTemplatePathPartiallyEquivalentSet.cs
- HelpPage.cs
- ConnectionStringSettingsCollection.cs
- TreeNodeBindingCollection.cs
- ValidationHelper.cs
- X509SubjectKeyIdentifierClause.cs
- Int64Storage.cs
- HtmlHead.cs
- ConfigurationStrings.cs
- ControlsConfig.cs
- MimeObjectFactory.cs
- Page.cs
- SimpleApplicationHost.cs
- WhitespaceRule.cs
- RightsManagementEncryptionTransform.cs
- URLString.cs
- FormsAuthenticationEventArgs.cs
- SaveFileDialog.cs
- Scalars.cs
- LineServicesRun.cs
- SubqueryRules.cs
- DataGridViewRowCancelEventArgs.cs
- ValidatingCollection.cs
- XhtmlConformanceSection.cs
- ElementFactory.cs
- xmlglyphRunInfo.cs
- MembershipAdapter.cs
- ValidationSettings.cs
- DataSvcMapFile.cs
- SQLGuidStorage.cs
- LicenseManager.cs
- GlyphRunDrawing.cs
- SingleStorage.cs
- RichTextBox.cs
- OracleRowUpdatingEventArgs.cs
- RsaSecurityKey.cs
- StructuredTypeInfo.cs
- PartDesigner.cs
- DBConnectionString.cs
- Journaling.cs
- Visitors.cs
- SpeechRecognitionEngine.cs
- MethodCallConverter.cs
- HWStack.cs
- DataSetUtil.cs
- BaseTemplateBuildProvider.cs
- TemplateManager.cs
- XmlSchemaObject.cs
- RsaSecurityTokenAuthenticator.cs
- SQLMembershipProvider.cs
- QuotedStringFormatReader.cs
- DockingAttribute.cs
- ListComponentEditorPage.cs
- HtmlTableRowCollection.cs
- SmtpAuthenticationManager.cs
- DataProtection.cs
- ItemContainerProviderWrapper.cs
- HashRepartitionEnumerator.cs
- TreeNodeCollection.cs
- Ops.cs
- XmlEventCache.cs
- XpsFontSerializationService.cs
- TextTreeObjectNode.cs
- SqlTriggerAttribute.cs
- HwndSource.cs
- ProcessMonitor.cs
- SplineKeyFrames.cs
- Int16Converter.cs
- MetadataLocation.cs
- XmlSerializerAssemblyAttribute.cs
- HandleExceptionArgs.cs
- DataSetFieldSchema.cs
- DataViewSetting.cs
- StorageMappingItemCollection.cs
- ListViewGroupConverter.cs
- ColorTransform.cs
- ServiceModelExtensionElement.cs
- MaskedTextBox.cs
- FactoryMaker.cs
- AlternateViewCollection.cs
- WindowsIPAddress.cs
- XmlSignatureManifest.cs
- HttpCookie.cs