Skip to content

Commit

Permalink
Add API to allow configuration of the association entity type. (#21672)
Browse files Browse the repository at this point in the history
* Add API to allow configuration of the association entity type.

Co-authored-by: lajones <lajones@microsoft.com>
  • Loading branch information
ajcvickers and lajones authored Jul 18, 2020
1 parent 3ebfde7 commit d2b9f32
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,25 @@ public CollectionCollectionBuilder(
[EntityFrameworkInternal]
protected virtual InternalModelBuilder ModelBuilder => LeftEntityType.AsEntityType().Model.Builder;

/// <summary>
/// Configures the association entity type implementing the many-to-many relationship.
/// </summary>
/// <param name="configureAssociation"> The configuration of the association type. </param>
/// <returns> The builder for the originating entity type so that multiple configuration calls can be chained. </returns>
public virtual EntityTypeBuilder UsingEntity(
[NotNull] Action<EntityTypeBuilder> configureAssociation)
{
Check.DebugAssert(LeftNavigation.AssociationEntityType != null, "LeftNavigation.AssociationEntityType is null");
Check.DebugAssert(RightNavigation.AssociationEntityType != null, "RightNavigation.AssociationEntityType is null");
Check.DebugAssert(LeftNavigation.AssociationEntityType == RightNavigation.AssociationEntityType,
"LeftNavigation.AssociationEntityType != RightNavigation.AssociationEntityType");

var associationEntityTypeBuilder = new EntityTypeBuilder(LeftNavigation.AssociationEntityType);
configureAssociation(associationEntityTypeBuilder);

return new EntityTypeBuilder(RightEntityType);
}

/// <summary>
/// Configures the relationships to the entity types participating in the many-to-many relationship.
/// </summary>
Expand Down
19 changes: 19 additions & 0 deletions src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ public CollectionCollectionBuilder(
{
}

/// <summary>
/// Configures the association entity type implementing the many-to-many relationship.
/// </summary>
/// <param name="configureAssociation"> The configuration of the association type. </param>
/// <returns> The builder for the originating entity type so that multiple configuration calls can be chained. </returns>
public new virtual EntityTypeBuilder<TRightEntity> UsingEntity(
[NotNull] Action<EntityTypeBuilder> configureAssociation)
{
Check.DebugAssert(LeftNavigation.AssociationEntityType != null, "LeftNavigation.AssociationEntityType is null");
Check.DebugAssert(RightNavigation.AssociationEntityType != null, "RightNavigation.AssociationEntityType is null");
Check.DebugAssert(LeftNavigation.AssociationEntityType == RightNavigation.AssociationEntityType,
"LeftNavigation.AssociationEntityType != RightNavigation.AssociationEntityType");

var associationEntityTypeBuilder = new EntityTypeBuilder(LeftNavigation.AssociationEntityType);
configureAssociation(associationEntityTypeBuilder);

return new EntityTypeBuilder<TRightEntity>(RightEntityType);
}

/// <summary>
/// Configures the relationships to the entity types participating in the many-to-many relationship.
/// </summary>
Expand Down
132 changes: 132 additions & 0 deletions test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,138 @@ public virtual void Many_to_many_join_table_stored_in_snapshot()
});
}


[ConditionalFact]
public virtual void Can_override_table_name_for_many_to_many_join_table_stored_in_snapshot()
{
Test(
builder =>
{
var manyToMany = builder
.Entity<ManyToManyLeft>()
.HasMany(l => l.Rights)
.WithMany(r => r.Lefts)
.UsingEntity(a => a.ToTable("MyJoinTable"));
},
AddBoilerPlate(
GetHeading()
+ @"
modelBuilder.Entity(""ManyToManyLeftManyToManyRight"", b =>
{
b.Property<int?>(""ManyToManyLeft_Id"")
.HasColumnType(""int"");
b.Property<int?>(""ManyToManyRight_Id"")
.HasColumnType(""int"");
b.HasKey(""ManyToManyLeft_Id"", ""ManyToManyRight_Id"");
b.HasIndex(""ManyToManyRight_Id"");
b.ToTable(""MyJoinTable"");
});
modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+ManyToManyLeft"", b =>
{
b.Property<int>(""Id"")
.ValueGeneratedOnAdd()
.HasColumnType(""int"")
.UseIdentityColumn();
b.Property<string>(""Name"")
.HasColumnType(""nvarchar(max)"");
b.HasKey(""Id"");
b.ToTable(""ManyToManyLeft"");
});
modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+ManyToManyRight"", b =>
{
b.Property<int>(""Id"")
.ValueGeneratedOnAdd()
.HasColumnType(""int"")
.UseIdentityColumn();
b.Property<string>(""Description"")
.HasColumnType(""nvarchar(max)"");
b.HasKey(""Id"");
b.ToTable(""ManyToManyRight"");
});
modelBuilder.Entity(""ManyToManyLeftManyToManyRight"", b =>
{
b.HasOne(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+ManyToManyLeft"", null)
.WithMany()
.HasForeignKey(""ManyToManyLeft_Id"")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+ManyToManyRight"", null)
.WithMany()
.HasForeignKey(""ManyToManyRight_Id"")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});", usingSystem: true),
model =>
{
var associationEntity = model.FindEntityType("ManyToManyLeftManyToManyRight");
Assert.NotNull(associationEntity);
Assert.Equal("MyJoinTable", associationEntity.GetTableName());
Assert.Collection(associationEntity.GetDeclaredProperties(),
p =>
{
Assert.Equal("ManyToManyLeft_Id", p.Name);
Assert.True(p.IsShadowProperty());
},
p =>
{
Assert.Equal("ManyToManyRight_Id", p.Name);
Assert.True(p.IsShadowProperty());
});
Assert.Collection(associationEntity.FindDeclaredPrimaryKey().Properties,
p =>
{
Assert.Equal("ManyToManyLeft_Id", p.Name);
},
p =>
{
Assert.Equal("ManyToManyRight_Id", p.Name);
});
Assert.Collection(associationEntity.GetDeclaredForeignKeys(),
fk =>
{
Assert.Equal("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+ManyToManyLeft", fk.PrincipalEntityType.Name);
Assert.Collection(fk.PrincipalKey.Properties,
p =>
{
Assert.Equal("Id", p.Name);
});
Assert.Collection(fk.Properties,
p =>
{
Assert.Equal("ManyToManyLeft_Id", p.Name);
});
},
fk =>
{
Assert.Equal("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+ManyToManyRight", fk.PrincipalEntityType.Name);
Assert.Collection(fk.PrincipalKey.Properties,
p =>
{
Assert.Equal("Id", p.Name);
});
Assert.Collection(fk.Properties,
p =>
{
Assert.Equal("ManyToManyRight_Id", p.Name);
});
});
});
}

[ConditionalFact]
public virtual void TableName_preserved_when_generic()
{
Expand Down

0 comments on commit d2b9f32

Please sign in to comment.