public void Initialize_should_create_association_ends()
        {
            var associationType = new EdmAssociationType().Initialize();

            Assert.NotNull(associationType.SourceEnd);
            Assert.NotNull(associationType.TargetEnd);
        }
        public void Apply_should_discover_for_self_reference()
        {
            var associationType = new EdmAssociationType().Initialize();

            associationType.SourceEnd.EndKind = EdmAssociationEndKind.Optional;
            associationType.SourceEnd.EntityType = new EdmEntityType();

            associationType.TargetEnd.EndKind = EdmAssociationEndKind.Many;
            associationType.TargetEnd.EntityType = associationType.SourceEnd.EntityType;

            var pkProperty = new EdmProperty().AsPrimitive();
            associationType.SourceEnd.EntityType.DeclaredKeyProperties.Add(pkProperty);

            var fkProperty = new EdmProperty().AsPrimitive();
            associationType.TargetEnd.EntityType.DeclaredProperties.Add(fkProperty);
            associationType.TargetEnd.EntityType.AddNavigationProperty("Nav", associationType).ResultEnd = associationType.SourceEnd;
            associationType.TargetEnd.EntityType.AddNavigationProperty("Foos", associationType);

            // Foo.Id == Foo.NavId
            pkProperty.Name = "Id";
            fkProperty.Name = "NavId";

            ((IEdmConvention<EdmAssociationType>)new NavigationPropertyNameForeignKeyDiscoveryConvention())
                .Apply(associationType, new EdmModel().Initialize());

            Assert.NotNull(associationType.Constraint);
            Assert.Same(associationType.TargetEnd, associationType.Constraint.DependentEnd);
            Assert.Equal("NavId", associationType.Constraint.DependentProperties.Single().Name);
        }
        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));
        }
        public void Can_get_and_set_configuration_facet()
        {
            var associationType = new EdmAssociationType().Initialize();
            associationType.SetConfiguration(42);

            Assert.Equal(42, associationType.GetConfiguration());
        }
        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 Apply_should_introduce_cascade_delete_on_constraints()
        {
            var databaseMapping
                = new DbDatabaseMapping()
                    .Initialize(new EdmModel().Initialize(), new DbDatabaseMetadata().Initialize());

            var foreignKeyConstraint = new DbForeignKeyConstraintMetadata();

            Assert.Equal(DbOperationAction.None, foreignKeyConstraint.DeleteAction);

            var table = new DbTableMetadata();
            table.ForeignKeyConstraints.Add(foreignKeyConstraint);

            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EndKind = EdmAssociationEndKind.Many;
            associationType.SourceEnd.EntityType = new EdmEntityType();
            associationType.TargetEnd.EndKind = EdmAssociationEndKind.Many;
            associationType.TargetEnd.EntityType = new EdmEntityType();

            var associationSetMapping = databaseMapping.AddAssociationSetMapping(new EdmAssociationSet { ElementType = associationType });
            associationSetMapping.Table = table;

            ((IDbMappingConvention)new ManyToManyCascadeDeleteConvention()).Apply(databaseMapping);

            Assert.Equal(DbOperationAction.Cascade, foreignKeyConstraint.DeleteAction);
        }
        public void IsManyToRequired_should_be_true_when_source_many_and_target_required()
        {
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EndKind = EdmAssociationEndKind.Many;
            associationType.TargetEnd.EndKind = EdmAssociationEndKind.Required;

            Assert.True(associationType.IsManyToRequired());
        }
 internal override void Configure(
     EdmAssociationType associationType, EdmAssociationEnd dependentEnd,
     EntityTypeConfiguration entityTypeConfiguration)
 {
     //Contract.Requires(associationType != null);
     //Contract.Requires(dependentEnd != null);
     //Contract.Requires(entityTypeConfiguration != null);
 }
        public static void SetAssociationType(
            this DbForeignKeyConstraintMetadata fk, EdmAssociationType associationType)
        {
            Contract.Requires(fk != null);
            Contract.Requires(associationType != null);

            fk.Annotations.SetAnnotation(AssociationType, associationType);
        }
        public void Configure_should_throw_when_dependent_property_not_found()
        {
            var constraintConfiguration = new ForeignKeyConstraintConfiguration(new[] { new MockPropertyInfo(typeof(int), "P").Object });
            var associationType = new EdmAssociationType();

            Assert.Equal(Strings.ForeignKeyPropertyNotFound("P", "T"), Assert.Throws<InvalidOperationException>(() => constraintConfiguration.Configure(associationType,
                                                                                                                                                              new EdmAssociationEnd { EntityType = new EdmEntityType { Name = "T" } }, new EntityTypeConfiguration(typeof(object)))).Message);
        }
        public void Can_mark_association_as_independent()
        {
            var associationType = new EdmAssociationType();

            Assert.False(associationType.IsIndependent());

            associationType.MarkIndependent();

            Assert.True(associationType.IsIndependent());
        }
        public void Apply_should_not_discover_when_independent_constraint()
        {
            var associationType = new EdmAssociationType().Initialize();
            associationType.MarkIndependent();

            ((IEdmConvention<EdmAssociationType>)new TypeNameForeignKeyDiscoveryConvention())
                .Apply(associationType, new EdmModel().Initialize());

            Assert.Null(associationType.Constraint);
        }
        public void AddNavigationProperty_should_create_and_add_navigation_property()
        {
            var entityType = new EdmEntityType();
            var associationType = new EdmAssociationType();

            var navigationProperty = entityType.AddNavigationProperty("N", associationType);

            Assert.NotNull(navigationProperty);
            Assert.Equal("N", navigationProperty.Name);
            Assert.Same(associationType, navigationProperty.Association);
            Assert.True(entityType.NavigationProperties.Contains(navigationProperty));
        }
        public void Apply_should_not_discover_when_no_clear_principal()
        {
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EndKind
                = associationType.TargetEnd.EndKind
                  = EdmAssociationEndKind.Many;

            ((IEdmConvention<EdmAssociationType>)new TypeNameForeignKeyDiscoveryConvention())
                .Apply(associationType, new EdmModel().Initialize());

            Assert.Null(associationType.Constraint);
        }
 private static void FixNavigationProperties(
     EdmModel model, EdmAssociationType unifiedAssociation, EdmAssociationType redundantAssociation)
 {
     foreach (var navigationProperty
         in model.GetEntityTypes()
             .SelectMany(e => e.NavigationProperties)
             .Where(np => np.Association == redundantAssociation))
     {
         navigationProperty.Association = unifiedAssociation;
         navigationProperty.ResultEnd = unifiedAssociation.SourceEnd;
     }
 }
        public void Apply_should_not_discover_when_existing_constraint()
        {
            var associationType = new EdmAssociationType().Initialize();
            var associationConstraint = new EdmAssociationConstraint();

            associationType.Constraint = associationConstraint;

            ((IEdmConvention<EdmAssociationType>)new TypeNameForeignKeyDiscoveryConvention())
                .Apply(associationType, new EdmModel().Initialize());

            Assert.Same(associationConstraint, associationType.Constraint);
        }
        public void Apply_should_not_add_action_when_self_reference()
        {
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EntityType
                = associationType.TargetEnd.EntityType
                    = new EdmEntityType();

            ((IEdmConvention<EdmAssociationType>)new OneToManyCascadeDeleteConvention())
                .Apply(associationType, new EdmModel().Initialize());

            Assert.Equal(null, associationType.SourceEnd.DeleteAction);
            Assert.Equal(null, associationType.TargetEnd.DeleteAction);
        }
        public void Apply_should_not_add_action_when_has_existing_action()
        {
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EntityType = new EdmEntityType();
            associationType.TargetEnd.EntityType = new EdmEntityType();
            associationType.SourceEnd.DeleteAction = EdmOperationAction.Restrict;

            ((IEdmConvention<EdmAssociationType>)new OneToManyCascadeDeleteConvention())
                .Apply(associationType, new EdmModel().Initialize());

            Assert.Equal(EdmOperationAction.Restrict, associationType.SourceEnd.DeleteAction);
            Assert.Equal(null, associationType.TargetEnd.DeleteAction);
        }
        public void Apply_is_noop_when_unknown_dependent()
        {
            var model = new EdmModel().Initialize();
            var associationType = new EdmAssociationType().Initialize();
            var navigationProperty = new EdmNavigationProperty { Association = associationType };
            var foreignKeyAnnotation = new ForeignKeyAttribute("AId");
            navigationProperty.Annotations.SetClrAttributes(new[] { foreignKeyAnnotation });

            ((IEdmConvention<EdmNavigationProperty>)new ForeignKeyNavigationPropertyAttributeConvention())
                .Apply(navigationProperty, model);

            Assert.Null(associationType.Constraint);
        }
        public void HasCascadeDeletePath_should_return_true_for_self_ref_cascade()
        {
            var model = new EdmModel().Initialize();
            var entityType = model.AddEntityType("A");
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EntityType
                = associationType.TargetEnd.EntityType
                  = entityType;
            associationType.SourceEnd.DeleteAction = EdmOperationAction.Cascade;
            model.AddAssociationType(associationType);

            Assert.True(model.HasCascadeDeletePath(entityType, entityType));
        }
        public void Apply_should_add_action_when_is_many_to_required()
        {
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EntityType = new EdmEntityType();
            associationType.TargetEnd.EntityType = new EdmEntityType();
            associationType.SourceEnd.EndKind = EdmAssociationEndKind.Many;
            associationType.TargetEnd.EndKind = EdmAssociationEndKind.Required;

            ((IEdmConvention<EdmAssociationType>)new OneToManyCascadeDeleteConvention())
                .Apply(associationType, new EdmModel().Initialize());

            Assert.Equal(EdmOperationAction.Cascade, associationType.TargetEnd.DeleteAction);
        }
        public void HasDeleteAction_should_be_true_if_either_end_is_not_none_action()
        {
            var associationType = new EdmAssociationType().Initialize();

            Assert.False(associationType.HasDeleteAction());

            associationType.SourceEnd.DeleteAction = EdmOperationAction.Cascade;

            Assert.True(associationType.HasDeleteAction());

            associationType = new EdmAssociationType().Initialize();
            associationType.TargetEnd.DeleteAction = EdmOperationAction.Cascade;

            Assert.True(associationType.HasDeleteAction());
        }
        public void Configure_should_add_properties_to_dependent_properties()
        {
            var mockPropertyInfo = new MockPropertyInfo(typeof(int), "P");
            var constraintConfiguration = new ForeignKeyConstraintConfiguration(new[] { mockPropertyInfo.Object });
            var entityType = new EdmEntityType();
            var property = entityType.AddPrimitiveProperty("P");
            property.PropertyType.EdmType = EdmPrimitiveType.Int32;
            property.SetClrPropertyInfo(mockPropertyInfo);
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EntityType = entityType;
            
            constraintConfiguration.Configure(
                associationType, associationType.SourceEnd, new EntityTypeConfiguration(typeof(object)));

            Assert.Equal(1, associationType.Constraint.DependentProperties.Count);
        }
        public void Configure_should_configure_ends()
        {
            var navigationPropertyConfiguration = new NavigationPropertyConfiguration(new MockPropertyInfo())
                {
                    EndKind = EdmAssociationEndKind.Optional,
                    InverseEndKind = EdmAssociationEndKind.Many
                };
            var associationType = new EdmAssociationType().Initialize();

            navigationPropertyConfiguration.Configure(
                new EdmNavigationProperty { Association = associationType },
                new EdmModel(), new EntityTypeConfiguration(typeof(object)));

            Assert.Equal(EdmAssociationEndKind.Many, associationType.SourceEnd.EndKind);
            Assert.Equal(EdmAssociationEndKind.Optional, associationType.TargetEnd.EndKind);
        }
        public void Generate(EdmAssociationType associationType, DbDatabaseMapping databaseMapping)
        {
            //Contract.Requires(associationType != null);
            //Contract.Requires(databaseMapping != null);

            if (associationType.Constraint != null)
            {
                GenerateForeignKeyAssociationType(associationType, databaseMapping);
            }
            else if (associationType.IsManyToMany())
            {
                GenerateManyToManyAssociation(associationType, databaseMapping);
            }
            else
            {
                GenerateIndependentAssociationType(associationType, databaseMapping);
            }
        }
        public void Apply_should_introduce_constraint_when_one_to_one()
        {
            var associationType = new EdmAssociationType().Initialize();
            var entityType1 = new EdmEntityType();
            entityType1.DeclaredKeyProperties.Add(new EdmProperty().AsPrimitive());
            var entityType2 = new EdmEntityType();
            entityType2.DeclaredKeyProperties.Add(new EdmProperty().AsPrimitive());

            associationType.SourceEnd.EntityType = entityType2;
            associationType.TargetEnd.EntityType = entityType1;
            associationType.MarkPrincipalConfigured();

            ((IEdmConvention<EdmAssociationType>)new OneToOneConstraintIntroductionConvention())
                .Apply(associationType, new EdmModel());

            Assert.NotNull(associationType.Constraint);
            Assert.Equal(1, associationType.Constraint.DependentProperties.Count);
        }
        public void Configure_should_propagate_end_kind_to_keys_when_required()
        {
            var mockPropertyInfo = new MockPropertyInfo(typeof(int), "P");
            var constraintConfiguration = new ForeignKeyConstraintConfiguration(new[] { mockPropertyInfo.Object });
            var entityType = new EdmEntityType();
            var property = entityType.AddPrimitiveProperty("P");
            property.PropertyType.EdmType = EdmPrimitiveType.Int32;
            property.PropertyType.IsNullable = true;
            property.SetClrPropertyInfo(mockPropertyInfo);
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EntityType = entityType;
            associationType.TargetEnd.EndKind = EdmAssociationEndKind.Required;

            constraintConfiguration.Configure(
                associationType, associationType.SourceEnd, new EntityTypeConfiguration(typeof(object)));

            Assert.Equal(1, associationType.Constraint.DependentProperties.Count);
            Assert.Equal(false, property.PropertyType.IsNullable);
        }
        public void Apply_should_set_principal_end_kind_to_required_when_all_properties_not_nullable()
        {
            var associationType = new EdmAssociationType().Initialize();
            associationType.SourceEnd.EntityType = new EdmEntityType();
            associationType.SourceEnd.EndKind = EdmAssociationEndKind.Optional;
            associationType.TargetEnd.EntityType = new EdmEntityType();

            var associationConstraint = new EdmAssociationConstraint();
            associationConstraint.DependentProperties.Add(new EdmProperty().AsPrimitive());
            associationConstraint.DependentProperties.Add(new EdmProperty().AsPrimitive());
            associationConstraint.DependentProperties.Each(p => p.PropertyType.IsNullable = false);
            associationConstraint.DependentEnd = associationType.TargetEnd;

            associationType.Constraint = associationConstraint;

            ((IEdmConvention<EdmAssociationType>)new ForeignKeyAssociationMultiplicityConvention())
                .Apply(associationType, new EdmModel().Initialize());

            Assert.True(associationType.SourceEnd.IsRequired());
        }
        private void GenerateManyToManyAssociation(
            EdmAssociationType associationType, DbDatabaseMapping databaseMapping)
        {
            //Contract.Requires(associationType != null);
            //Contract.Requires(databaseMapping != null);

            var sourceEntityType = associationType.SourceEnd.EntityType;
            var targetEntityType = associationType.TargetEnd.EntityType;

            var joinTable
                = databaseMapping.Database.AddTable(sourceEntityType.Name + targetEntityType.Name);

            var associationSetMapping
                = GenerateAssociationSetMapping(
                    associationType, databaseMapping, associationType.SourceEnd, associationType.TargetEnd, joinTable);

            GenerateIndependentForeignKeyConstraint(
                databaseMapping,
                sourceEntityType,
                targetEntityType,
                joinTable,
                associationSetMapping,
                associationSetMapping.SourceEndMapping,
                associationType.SourceEnd.Name,
                null,
                isPrimaryKeyColumn: true);

            GenerateIndependentForeignKeyConstraint(
                databaseMapping,
                targetEntityType,
                sourceEntityType,
                joinTable,
                associationSetMapping,
                associationSetMapping.TargetEndMapping,
                associationType.TargetEnd.Name,
                null,
                isPrimaryKeyColumn: true);
        }
        public void HasCascadeDeletePath_should_return_true_for_transitive_cascade()
        {
            var model = new EdmModel().Initialize();
            var entityTypeA = model.AddEntityType("A");
            var entityTypeB = model.AddEntityType("B");
            var entityTypeC = model.AddEntityType("B");
            var associationTypeA = new EdmAssociationType().Initialize();
            associationTypeA.SourceEnd.EntityType = entityTypeA;
            associationTypeA.TargetEnd.EntityType = entityTypeB;
            associationTypeA.SourceEnd.DeleteAction = EdmOperationAction.Cascade;
            model.AddAssociationType(associationTypeA);
            var associationTypeB = new EdmAssociationType().Initialize();
            associationTypeB.SourceEnd.EntityType = entityTypeB;
            associationTypeB.TargetEnd.EntityType = entityTypeC;
            associationTypeB.SourceEnd.DeleteAction = EdmOperationAction.Cascade;
            model.AddAssociationType(associationTypeB);

            Assert.True(model.HasCascadeDeletePath(entityTypeA, entityTypeB));
            Assert.True(model.HasCascadeDeletePath(entityTypeB, entityTypeC));
            Assert.True(model.HasCascadeDeletePath(entityTypeA, entityTypeC));
            Assert.False(model.HasCascadeDeletePath(entityTypeB, entityTypeA));
            Assert.False(model.HasCascadeDeletePath(entityTypeC, entityTypeB));
            Assert.False(model.HasCascadeDeletePath(entityTypeC, entityTypeA));
        }