Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / DynamicData / DynamicData / ModelProviders / EFAssociationProvider.cs / 1305376 / EFAssociationProvider.cs
using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data.Metadata.Edm; using System.Diagnostics; using System.Globalization; using System.Linq; #if ORYX_VNEXT using System.Web.DynamicData; #endif namespace System.Web.DynamicData.ModelProviders { internal sealed class EFAssociationProvider : AssociationProvider { public EFAssociationProvider(EFColumnProvider column, NavigationProperty navigationProperty) { FromColumn = column; var entityMemberParentEntity = (EFTableProvider)column.Table; var parentEntityModel = (EFDataModelProvider)entityMemberParentEntity.DataModel; EFColumnProvider columnProvider; EntityType otherEntityType = navigationProperty.ToEndMember.GetEntityType(); // If we can get to the entityType of the ToMember side of the relaionship then build a relationship key and try to lookup the column provider. if (otherEntityType != null) { long key = BuildRelationshipKey(otherEntityType, navigationProperty.ToEndMember); if (parentEntityModel.RelationshipEndLookup.TryGetValue(key, out columnProvider)) { ToColumn = columnProvider; } else { // Otherwise just lookup the entityType in the table lookup ToTable = parentEntityModel.TableEndLookup[otherEntityType]; } } else { EntityType value = (EntityType)navigationProperty.ToEndMember.TypeUsage.EdmType.MetadataProperties.Single(prop => prop.Name == "ElementType").Value; ToTable = parentEntityModel.TableEndLookup[value]; } if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { if (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { Direction = AssociationDirection.ManyToMany; } else { Direction = AssociationDirection.OneToMany; } } else { if (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { Direction = AssociationDirection.ManyToOne; } else { Direction = AssociationDirection.OneToOne; } } // If it's a foreign key reference (as opposed to a entity set), figure out the foreign keys if (IsForeignKeyReference) { var foreignKeyNames = new List(); var primaryKeyNames = FromColumn.Table.Columns.Where(c => c.IsPrimaryKey).Select(c => c.Name); // Add the foreign keys for this association. foreignKeyNames.AddRange(GetDependentPropertyNames(navigationProperty)); if (IsZeroOrOne(navigationProperty)) { // Assume this is true for 1 to 0..1 relationships on both sides IsPrimaryKeyInThisTable = true; } else { // If any of the foreign keys are also PKs, set the flag IsPrimaryKeyInThisTable = foreignKeyNames.Any(fkName => primaryKeyNames.Contains(fkName, StringComparer.OrdinalIgnoreCase)); } if (!foreignKeyNames.Any()) { // If we couldn't find any dependent properties, we're dealing with a model that doesn't // have FKs, and requires the use of flattened FK names (e.g. Category.CategoryId) foreach (ColumnProvider toEntityColumn in ToTable.Columns.Where(c => c.IsPrimaryKey)) { foreignKeyNames.Add(FromColumn.Name + "." + toEntityColumn.Name); } } ForeignKeyNames = foreignKeyNames.AsReadOnly(); } } private static bool IsZeroOrOne(NavigationProperty navigationProperty) { return (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One) || (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne); } private bool IsForeignKeyReference { get { return Direction == AssociationDirection.OneToOne || Direction == AssociationDirection.ManyToOne; } } internal static long BuildRelationshipKey(EntityType entityType, RelationshipEndMember member) { return Misc.CombineHashCodes(entityType.GetHashCode(), member.GetHashCode()); } internal static IEnumerable GetDependentPropertyNames(NavigationProperty navigationProperty) { return GetDependentPropertyNames(navigationProperty, true /*checkRelationshipType*/); } internal static IEnumerable GetDependentPropertyNames(NavigationProperty navigationProperty, bool checkRelationshipType) { if (checkRelationshipType) { if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One) { // Get constraint when this association is on the "parent" (aka "from") side. This means // that the navProperty represents a Children association in a 1-1 relationship. For example, // this could be a Item-ItemDetail scenario where the ItemDetail table has a PK that is also an FK // into the Item table (thus ensuring the 1-1 cardinality). We need to special case this situation because normally we would try // to build a foreign key name of the form "Item.ItemID", but we want just "ItemID". AssociationType relationshipType = (AssociationType)navigationProperty.RelationshipType; ReferentialConstraint constraint = relationshipType.ReferentialConstraints.FirstOrDefault(c => c.ToRole == navigationProperty.ToEndMember); if (constraint != null) { return constraint.FromProperties.Select(p => p.Name); } // Fall back on the primary keys if no constraints were found but only if we are on the parent side. i.e the 1 side Item side in an Item-ItemDetail // Get the primary keys on the "from" side of the relationship. i.e Product.Category -> ProductID return navigationProperty.FromEndMember.GetEntityType().KeyMembers.Select(m => m.Name); } } return navigationProperty.GetDependentProperties().Select(m => m.Name); } public override string GetSortExpression(ColumnProvider sortColumn) { return GetSortExpression(sortColumn, "it.{0}.{1}"); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data.Metadata.Edm; using System.Diagnostics; using System.Globalization; using System.Linq; #if ORYX_VNEXT using System.Web.DynamicData; #endif namespace System.Web.DynamicData.ModelProviders { internal sealed class EFAssociationProvider : AssociationProvider { public EFAssociationProvider(EFColumnProvider column, NavigationProperty navigationProperty) { FromColumn = column; var entityMemberParentEntity = (EFTableProvider)column.Table; var parentEntityModel = (EFDataModelProvider)entityMemberParentEntity.DataModel; EFColumnProvider columnProvider; EntityType otherEntityType = navigationProperty.ToEndMember.GetEntityType(); // If we can get to the entityType of the ToMember side of the relaionship then build a relationship key and try to lookup the column provider. if (otherEntityType != null) { long key = BuildRelationshipKey(otherEntityType, navigationProperty.ToEndMember); if (parentEntityModel.RelationshipEndLookup.TryGetValue(key, out columnProvider)) { ToColumn = columnProvider; } else { // Otherwise just lookup the entityType in the table lookup ToTable = parentEntityModel.TableEndLookup[otherEntityType]; } } else { EntityType value = (EntityType)navigationProperty.ToEndMember.TypeUsage.EdmType.MetadataProperties.Single(prop => prop.Name == "ElementType").Value; ToTable = parentEntityModel.TableEndLookup[value]; } if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { if (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { Direction = AssociationDirection.ManyToMany; } else { Direction = AssociationDirection.OneToMany; } } else { if (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { Direction = AssociationDirection.ManyToOne; } else { Direction = AssociationDirection.OneToOne; } } // If it's a foreign key reference (as opposed to a entity set), figure out the foreign keys if (IsForeignKeyReference) { var foreignKeyNames = new List (); var primaryKeyNames = FromColumn.Table.Columns.Where(c => c.IsPrimaryKey).Select(c => c.Name); // Add the foreign keys for this association. foreignKeyNames.AddRange(GetDependentPropertyNames(navigationProperty)); if (IsZeroOrOne(navigationProperty)) { // Assume this is true for 1 to 0..1 relationships on both sides IsPrimaryKeyInThisTable = true; } else { // If any of the foreign keys are also PKs, set the flag IsPrimaryKeyInThisTable = foreignKeyNames.Any(fkName => primaryKeyNames.Contains(fkName, StringComparer.OrdinalIgnoreCase)); } if (!foreignKeyNames.Any()) { // If we couldn't find any dependent properties, we're dealing with a model that doesn't // have FKs, and requires the use of flattened FK names (e.g. Category.CategoryId) foreach (ColumnProvider toEntityColumn in ToTable.Columns.Where(c => c.IsPrimaryKey)) { foreignKeyNames.Add(FromColumn.Name + "." + toEntityColumn.Name); } } ForeignKeyNames = foreignKeyNames.AsReadOnly(); } } private static bool IsZeroOrOne(NavigationProperty navigationProperty) { return (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One) || (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne); } private bool IsForeignKeyReference { get { return Direction == AssociationDirection.OneToOne || Direction == AssociationDirection.ManyToOne; } } internal static long BuildRelationshipKey(EntityType entityType, RelationshipEndMember member) { return Misc.CombineHashCodes(entityType.GetHashCode(), member.GetHashCode()); } internal static IEnumerable GetDependentPropertyNames(NavigationProperty navigationProperty) { return GetDependentPropertyNames(navigationProperty, true /*checkRelationshipType*/); } internal static IEnumerable GetDependentPropertyNames(NavigationProperty navigationProperty, bool checkRelationshipType) { if (checkRelationshipType) { if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne && navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One) { // Get constraint when this association is on the "parent" (aka "from") side. This means // that the navProperty represents a Children association in a 1-1 relationship. For example, // this could be a Item-ItemDetail scenario where the ItemDetail table has a PK that is also an FK // into the Item table (thus ensuring the 1-1 cardinality). We need to special case this situation because normally we would try // to build a foreign key name of the form "Item.ItemID", but we want just "ItemID". AssociationType relationshipType = (AssociationType)navigationProperty.RelationshipType; ReferentialConstraint constraint = relationshipType.ReferentialConstraints.FirstOrDefault(c => c.ToRole == navigationProperty.ToEndMember); if (constraint != null) { return constraint.FromProperties.Select(p => p.Name); } // Fall back on the primary keys if no constraints were found but only if we are on the parent side. i.e the 1 side Item side in an Item-ItemDetail // Get the primary keys on the "from" side of the relationship. i.e Product.Category -> ProductID return navigationProperty.FromEndMember.GetEntityType().KeyMembers.Select(m => m.Name); } } return navigationProperty.GetDependentProperties().Select(m => m.Name); } public override string GetSortExpression(ColumnProvider sortColumn) { return GetSortExpression(sortColumn, "it.{0}.{1}"); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- GcHandle.cs
- IsolatedStorageFile.cs
- BaseDataList.cs
- ResourceSet.cs
- DataRowCollection.cs
- JsonEnumDataContract.cs
- BulletedList.cs
- TextClipboardData.cs
- SQLString.cs
- XXXOnTypeBuilderInstantiation.cs
- AstTree.cs
- HttpFileCollectionWrapper.cs
- SourceChangedEventArgs.cs
- OleDbCommand.cs
- BuildResultCache.cs
- CounterSetInstanceCounterDataSet.cs
- Path.cs
- X509AsymmetricSecurityKey.cs
- RegularExpressionValidator.cs
- XmlNavigatorStack.cs
- Point4DConverter.cs
- SpeakCompletedEventArgs.cs
- ScriptDescriptor.cs
- FileCodeGroup.cs
- SchemaNamespaceManager.cs
- JoinCqlBlock.cs
- ContextQuery.cs
- UnsafeNetInfoNativeMethods.cs
- TCPClient.cs
- EventDescriptorCollection.cs
- HostingPreferredMapPath.cs
- RenderData.cs
- ObservableCollection.cs
- SpecialFolderEnumConverter.cs
- SemaphoreSecurity.cs
- ErrorView.xaml.cs
- SourceLocation.cs
- TypeConverterValueSerializer.cs
- GridItemPattern.cs
- XDRSchema.cs
- IResourceProvider.cs
- RecordsAffectedEventArgs.cs
- MarginCollapsingState.cs
- ByteViewer.cs
- regiisutil.cs
- SharedRuntimeState.cs
- SmiXetterAccessMap.cs
- SourceFileBuildProvider.cs
- SqlConnectionFactory.cs
- IndependentlyAnimatedPropertyMetadata.cs
- invalidudtexception.cs
- CheckedPointers.cs
- DynamicDataExtensions.cs
- SHA1.cs
- WizardStepBase.cs
- DataGridViewCellStyleConverter.cs
- RawKeyboardInputReport.cs
- ToolstripProfessionalRenderer.cs
- SetIndexBinder.cs
- DuplicateWaitObjectException.cs
- TaskFormBase.cs
- DoWorkEventArgs.cs
- MemberInfoSerializationHolder.cs
- SurrogateDataContract.cs
- HwndMouseInputProvider.cs
- ReferenceEqualityComparer.cs
- DataGridViewRowCollection.cs
- DelegateTypeInfo.cs
- ChangeToolStripParentVerb.cs
- LinqDataSourceInsertEventArgs.cs
- Exception.cs
- BitmapMetadataEnumerator.cs
- ISFClipboardData.cs
- SafeRightsManagementQueryHandle.cs
- PropertyConverter.cs
- Compiler.cs
- SiteMapNodeItemEventArgs.cs
- ItemCollectionEditor.cs
- DiscreteKeyFrames.cs
- SelectionListDesigner.cs
- TextPointerBase.cs
- BoolExpr.cs
- ExpressionVisitor.cs
- PeerCollaboration.cs
- ParameterToken.cs
- EncoderNLS.cs
- TracePayload.cs
- RouteValueExpressionBuilder.cs
- MetadataException.cs
- TextRangeEdit.cs
- StateValidator.cs
- AttributeProviderAttribute.cs
- AuthenticationSection.cs
- InputProviderSite.cs
- StatusBarDrawItemEvent.cs
- regiisutil.cs
- SequentialOutput.cs
- Int32CollectionConverter.cs
- ObjectHelper.cs
- ItemsControlAutomationPeer.cs