public void GetOtherEnd_should_return_correct_end() { var associationType = new EdmAssociationType().Initialize(); Assert.Same(associationType.SourceEnd, associationType.GetOtherEnd(associationType.TargetEnd)); Assert.Same(associationType.TargetEnd, associationType.GetOtherEnd(associationType.SourceEnd)); }
private static void GenerateForeignKeyAssociationType( EdmAssociationType associationType, DbDatabaseMapping databaseMapping) { //Contract.Requires(associationType != null); //Contract.Requires(databaseMapping != null); Contract.Assert(associationType.Constraint != null); var dependentEnd = associationType.Constraint.DependentEnd; var principalEnd = associationType.GetOtherEnd(dependentEnd); var principalEntityTypeMapping = GetEntityTypeMappingInHierarchy(databaseMapping, principalEnd.EntityType); var dependentEntityTypeMapping = GetEntityTypeMappingInHierarchy(databaseMapping, dependentEnd.EntityType); var foreignKeyConstraint = new DbForeignKeyConstraintMetadata { Name = associationType.Name, PrincipalTable = principalEntityTypeMapping.TypeMappingFragments.Single().Table, DeleteAction = principalEnd.DeleteAction.HasValue ? (DbOperationAction)principalEnd.DeleteAction.Value : DbOperationAction.None }; foreach (var dependentProperty in associationType.Constraint.DependentProperties) { foreignKeyConstraint.DependentColumns.Add( dependentEntityTypeMapping.GetPropertyMapping(dependentProperty).Column); } foreignKeyConstraint.SetAssociationType(associationType); dependentEntityTypeMapping .TypeMappingFragments .Single() .Table .ForeignKeyConstraints.Add(foreignKeyConstraint); }
private void ConfigureDependentBehavior( EdmAssociationType associationType, EdmModel model, EntityTypeConfiguration entityTypeConfiguration) { //Contract.Requires(associationType != null); //Contract.Requires(model != null); //Contract.Requires(entityTypeConfiguration != null); EdmAssociationEnd principalEnd; EdmAssociationEnd dependentEnd; if (!associationType.TryGuessPrincipalAndDependentEnds(out principalEnd, out dependentEnd)) { if (IsNavigationPropertyDeclaringTypePrincipal.HasValue) { associationType.MarkPrincipalConfigured(); var navProp = model.Namespaces .SelectMany(ns => ns.EntityTypes) .SelectMany(et => et.DeclaredNavigationProperties) .Where(np => np.GetClrPropertyInfo().IsSameAs(NavigationProperty)) .Single(); principalEnd = IsNavigationPropertyDeclaringTypePrincipal.Value ? associationType.GetOtherEnd(navProp.ResultEnd) : navProp.ResultEnd; dependentEnd = associationType.GetOtherEnd(principalEnd); if (associationType.SourceEnd != principalEnd) { // need to move around source to be principal, target to be dependent so Edm services will use the correct // principal and dependent ends. The Edm default Db + mapping service tries to guess principal/dependent // based on multiplicities, but if it can't figure it out, it will use source as principal and target as dependent associationType.SourceEnd = principalEnd; associationType.TargetEnd = dependentEnd; var associationSet = model.Containers .SelectMany(ct => ct.AssociationSets) .Where(aset => aset.ElementType == associationType).Single(); var sourceSet = associationSet.SourceSet; associationSet.SourceSet = associationSet.TargetSet; associationSet.TargetSet = sourceSet; } } if (principalEnd == null) { dependentEnd = associationType.TargetEnd; } } ConfigureConstraint(associationType, dependentEnd, entityTypeConfiguration); ConfigureDeleteAction(associationType.GetOtherEnd(dependentEnd)); }
internal override void Configure( EdmAssociationType associationType, EdmAssociationEnd dependentEnd, EntityTypeConfiguration entityTypeConfiguration) { if (!_dependentProperties.Any()) { return; } var associationConstraint = new EdmAssociationConstraint { DependentEnd = dependentEnd }; var dependentProperties = _dependentProperties.AsEnumerable(); if (!IsFullySpecified) { var foreignKeys = from p in _dependentProperties select new { PropertyInfo = p, entityTypeConfiguration.Property(new PropertyPath(p)).ColumnOrder }; if ((_dependentProperties.Count > 1) && foreignKeys.Any(p => !p.ColumnOrder.HasValue)) { var dependentKeys = dependentEnd.EntityType.DeclaredKeyProperties; if ((dependentKeys.Count == _dependentProperties.Count) && foreignKeys.All(fk => dependentKeys.Any(p => p.GetClrPropertyInfo().IsSameAs(fk.PropertyInfo)))) { // The FK and PK sets are equal, we know the order dependentProperties = dependentKeys.Select(p => p.GetClrPropertyInfo()); } else { throw Error.ForeignKeyAttributeConvention_OrderRequired(entityTypeConfiguration.ClrType); } } else { dependentProperties = foreignKeys.OrderBy(p => p.ColumnOrder).Select(p => p.PropertyInfo); } } foreach (var dependentProperty in dependentProperties) { var property = associationConstraint .DependentEnd .EntityType .GetDeclaredPrimitiveProperty(dependentProperty); if (property == null) { throw Error.ForeignKeyPropertyNotFound( dependentProperty.Name, associationConstraint.DependentEnd.EntityType.Name); } associationConstraint.DependentProperties.Add(property); } associationType.Constraint = associationConstraint; var principalEnd = associationType.GetOtherEnd(dependentEnd); if (principalEnd.IsRequired()) { associationType.Constraint.DependentProperties.Each(p => p.PropertyType.IsNullable = false); } }
private static void UpdatePrincipalTables( DbDatabaseMapping databaseMapping, DbTableMetadata toTable, bool removeFks, EdmAssociationType associationType, EdmEntityType et) { EdmAssociationEnd principalEnd, dependentEnd; var endsToCheck = new List<EdmAssociationEnd>(); if (associationType.TryGuessPrincipalAndDependentEnds(out principalEnd, out dependentEnd)) { endsToCheck.Add(principalEnd); } else if (associationType.SourceEnd.EndKind == EdmAssociationEndKind.Many && associationType.TargetEnd.EndKind == EdmAssociationEndKind.Many) { // many to many consider both ends endsToCheck.Add(associationType.SourceEnd); endsToCheck.Add(associationType.TargetEnd); } else { // 1:1 and 0..1:0..1 endsToCheck.Add(associationType.SourceEnd); } foreach (var end in endsToCheck) { if (end.EntityType == et) { IEnumerable<KeyValuePair<DbTableMetadata, IEnumerable<DbTableColumnMetadata>>> dependentTableInfos; if (associationType.Constraint != null) { var originalDependentType = associationType.GetOtherEnd(end).EntityType; var allDependentTypes = databaseMapping.Model.GetSelfAndAllDerivedTypes(originalDependentType); dependentTableInfos = allDependentTypes.Select(t => databaseMapping.GetEntityTypeMapping(t)).Where( dm => dm != null) .SelectMany( dm => dm.TypeMappingFragments .Where( tmf => associationType.Constraint.DependentProperties .All( p => tmf.PropertyMappings.Any( pm => pm.PropertyPath.First() == p)))) .Distinct((f1, f2) => f1.Table == f2.Table) .Select( df => new KeyValuePair<DbTableMetadata, IEnumerable<DbTableColumnMetadata>>( df.Table, df.PropertyMappings.Where( pm => associationType.Constraint.DependentProperties.Contains( pm.PropertyPath.First())).Select( pm => pm.Column))); } else { // IA var associationSetMapping = databaseMapping.EntityContainerMappings.Single().AssociationSetMappings.Where( asm => asm.AssociationSet.ElementType == associationType).Single(); var dependentTable = associationSetMapping.Table; var propertyMappings = associationSetMapping.SourceEndMapping.AssociationEnd == end ? associationSetMapping.SourceEndMapping.PropertyMappings : associationSetMapping.TargetEndMapping.PropertyMappings; var dependentColumns = propertyMappings.Select(pm => pm.Column); dependentTableInfos = new[] { new KeyValuePair <DbTableMetadata, IEnumerable<DbTableColumnMetadata>>( dependentTable, dependentColumns) }; } foreach (var tableInfo in dependentTableInfos) { foreach ( var fk in tableInfo.Key.ForeignKeyConstraints.Where( fk => fk.DependentColumns.SequenceEqual(tableInfo.Value)).ToArray( )) { if (removeFks) { tableInfo.Key.ForeignKeyConstraints.Remove(fk); } else { fk.PrincipalTable = toTable; } } } } } }