void IEdmConvention.Apply(EdmModel model) { var associationPairs = (from a1 in model.GetAssociationTypes() from a2 in model.GetAssociationTypes() where a1 != a2 where a1.SourceEnd.EntityType == a2.TargetEnd.EntityType && a1.TargetEnd.EntityType == a2.SourceEnd.EntityType let a1Configuration = a1.GetConfiguration() as NavigationPropertyConfiguration let a2Configuration = a2.GetConfiguration() as NavigationPropertyConfiguration where (((a1Configuration == null) || ((a1Configuration.InverseEndKind == null) && (a1Configuration.InverseNavigationProperty == null))) && ((a2Configuration == null) || ((a2Configuration.InverseEndKind == null) && (a2Configuration.InverseNavigationProperty == null)))) select new { a1, a2 }) .Distinct((a, b) => a.a1 == b.a2 && a.a2 == b.a1) .GroupBy( (a, b) => a.a1.SourceEnd.EntityType == b.a2.TargetEnd.EntityType && a.a1.TargetEnd.EntityType == b.a2.SourceEnd.EntityType) .Where(g => g.Count() == 1) .Select(g => g.Single()); foreach (var pair in associationPairs) { var unifiedAssociation = pair.a2.GetConfiguration() != null ? pair.a2 : pair.a1; var redundantAssociation = unifiedAssociation == pair.a1 ? pair.a2 : pair.a1; unifiedAssociation.SourceEnd.EndKind = redundantAssociation.TargetEnd.EndKind; if (redundantAssociation.Constraint != null) { unifiedAssociation.Constraint = redundantAssociation.Constraint; unifiedAssociation.Constraint.DependentEnd = unifiedAssociation.Constraint.DependentEnd.EntityType == unifiedAssociation.SourceEnd.EntityType ? unifiedAssociation.SourceEnd : unifiedAssociation.TargetEnd; } FixNavigationProperties(model, unifiedAssociation, redundantAssociation); model.RemoveAssociationType(redundantAssociation); } }
public void Configure_should_configure_inverse() { var inverseMockPropertyInfo = new MockPropertyInfo(); var navigationPropertyConfiguration = new NavigationPropertyConfiguration(new MockPropertyInfo()) { InverseNavigationProperty = inverseMockPropertyInfo }; var associationType = new EdmAssociationType().Initialize(); var inverseAssociationType = new EdmAssociationType().Initialize(); var model = new EdmModel().Initialize(); model.AddAssociationType(inverseAssociationType); var inverseNavigationProperty = model.AddEntityType("T") .AddNavigationProperty("N", inverseAssociationType); inverseNavigationProperty.SetClrPropertyInfo(inverseMockPropertyInfo); navigationPropertyConfiguration.Configure( new EdmNavigationProperty { Association = associationType }, model, new EntityTypeConfiguration(typeof(object))); Assert.Same(associationType, inverseNavigationProperty.Association); Assert.Same(associationType.SourceEnd, inverseNavigationProperty.ResultEnd); Assert.Equal(0, model.GetAssociationTypes().Count()); }
public void RemoveAssociationType_should_remove_type_and_set() { var model = new EdmModel().Initialize(); var associationType = model.AddAssociationType( "A", new EdmEntityType(), EdmAssociationEndKind.Optional, new EdmEntityType(), EdmAssociationEndKind.Many); model.AddAssociationSet("FooSet", associationType); model.RemoveAssociationType(associationType); Assert.Equal(0, model.GetAssociationTypes().Count()); Assert.Equal(0, model.Containers.First().AssociationSets.Count()); }
public void GetAssociationTypes_should_return_correct_types() { var model = new EdmModel().Initialize(); Assert.Same(model.Namespaces.First().AssociationTypes, model.GetAssociationTypes()); }
void IEdmConvention.Apply(EdmModel model) { // Query the model for candidate complex types. // - The rules for complex type discovery are as follows: // 1) The entity does not have a key or base type. // 2) The entity does not have explicit configuration or has only structural type configuration. // 3) The entity does not have any outbound navigation properties. // The entity only has inbound associations where: // 4) The association does not have a constraint defined. // 5) The association does not have explicit configuration. // 6) The association is not self-referencing. // 7) The other end of the association is Optional. // 8) Any inbound navigation properties do not have explicit configuration. var candidates = from entityType in model.GetEntityTypes() where entityType.DeclaredKeyProperties.Count == 0 // (1) && entityType.BaseType == null // (1) let entityTypeConfiguration = entityType.GetConfiguration() as EntityTypeConfiguration where ((entityTypeConfiguration == null) // (2) || (!entityTypeConfiguration.IsExplicitEntity && entityTypeConfiguration.IsStructuralConfigurationOnly)) // (2) && !entityType.NavigationProperties.Any() // (3) let matchingAssociations = from associationType in model.GetAssociationTypes() where associationType.SourceEnd.EntityType == entityType || associationType.TargetEnd.EntityType == entityType let declaringEnd = associationType.SourceEnd.EntityType == entityType ? associationType.SourceEnd : associationType.TargetEnd let declaringEntity = associationType.GetOtherEnd(declaringEnd).EntityType let navigationProperties = declaringEntity.NavigationProperties .Where(n => n.ResultEnd.EntityType == entityType) select new { DeclaringEnd = declaringEnd, AssociationType = associationType, DeclaringEntityType = declaringEntity, NavigationProperties = navigationProperties.ToList() } where matchingAssociations.All( a => a.AssociationType.Constraint == null // (4) && a.AssociationType.GetConfiguration() == null // (5) && !a.AssociationType.IsSelfReferencing() // (6) && a.DeclaringEnd.IsOptional() // (7) && a.NavigationProperties.All(n => n.GetConfiguration() == null)) // (8) select new { EntityType = entityType, MatchingAssociations = matchingAssociations.ToList(), }; // Transform candidate entities into complex types foreach (var candidate in candidates.ToList()) { var complexType = model.AddComplexType(candidate.EntityType.Name); foreach (var property in candidate.EntityType.DeclaredProperties) { complexType.DeclaredProperties.Add(property); } foreach (var annotation in candidate.EntityType.Annotations) { complexType.Annotations.Add(annotation); } foreach (var association in candidate.MatchingAssociations) { foreach (var navigationProperty in association.NavigationProperties) { if (association.DeclaringEntityType.NavigationProperties.Contains(navigationProperty)) { association.DeclaringEntityType.DeclaredNavigationProperties.Remove(navigationProperty); var complexProperty = association.DeclaringEntityType.AddComplexProperty(navigationProperty.Name, complexType); foreach (var annotation in navigationProperty.Annotations) { complexProperty.Annotations.Add(annotation); } } } model.RemoveAssociationType(association.AssociationType); } model.RemoveEntityType(candidate.EntityType); } }
private void GenerateAssociationTypes(EdmModel model, DbDatabaseMapping databaseMapping) { //Contract.Requires(model != null); //Contract.Requires(databaseMapping != null); foreach (var associationType in model.GetAssociationTypes()) { new AssociationTypeMappingGenerator(_providerManifest) .Generate(associationType, databaseMapping); } }