diff --git a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs index cff7bab72ab..af0a260930d 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs @@ -828,8 +828,17 @@ protected virtual void GenerateEntityTypeAnnotations( { if (((bool?)isExcludedAnnotation.Value) == true) { - stringBuilder - .Append(", t => t.ExcludeFromMigrations()"); + if (entityType.IsOwned()) + { + // Issue #23173 + stringBuilder + .Append(", excludedFromMigrations: true"); + } + else + { + stringBuilder + .Append(", t => t.ExcludeFromMigrations()"); + } } annotations.Remove(isExcludedAnnotation.Name); diff --git a/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs index 860a17fee63..e5c2df2d83c 100644 --- a/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs @@ -197,7 +197,10 @@ public static EntityTypeBuilder ToTable( public static OwnedNavigationBuilder ToTable( [NotNull] this OwnedNavigationBuilder referenceOwnershipBuilder, [CanBeNull] string name) - => referenceOwnershipBuilder.ToTable(name, excludedFromMigrations: false); + => ToTable(referenceOwnershipBuilder, name, schema: null, excludedFromMigrations: + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue23137", out var isEnabled) && isEnabled + ? false + : (bool?)null); /// /// Configures the table that the entity type maps to when targeting a relational database. @@ -226,7 +229,10 @@ public static OwnedNavigationBuilder ToTable (OwnedNavigationBuilder)ToTable( - (OwnedNavigationBuilder)referenceOwnershipBuilder, name, excludedFromMigrations: false); + referenceOwnershipBuilder, name, schema: null, excludedFromMigrations: + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue23137", out var isEnabled) && isEnabled + ? false + : (bool?)null); /// /// Configures the table that the entity type maps to when targeting a relational database. @@ -257,7 +263,10 @@ public static OwnedNavigationBuilder ToTable( [NotNull] this OwnedNavigationBuilder referenceOwnershipBuilder, [CanBeNull] string name, [CanBeNull] string schema) - => referenceOwnershipBuilder.ToTable(name, schema, excludedFromMigrations: false); + => ToTable(referenceOwnershipBuilder, name, schema, excludedFromMigrations: + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue23137", out var isEnabled) && isEnabled + ? false + : (bool?)null); /// /// Configures the table that the entity type maps to when targeting a relational database. @@ -277,9 +286,22 @@ public static OwnedNavigationBuilder ToTable( Check.NullButNotEmpty(name, nameof(name)); Check.NullButNotEmpty(schema, nameof(schema)); + return ToTable(referenceOwnershipBuilder, name, schema, (bool?)excludedFromMigrations); + } + + private static OwnedNavigationBuilder ToTable( + OwnedNavigationBuilder referenceOwnershipBuilder, + string name, + string schema, + bool? excludedFromMigrations) + { referenceOwnershipBuilder.OwnedEntityType.SetTableName(name); referenceOwnershipBuilder.OwnedEntityType.SetSchema(schema); - referenceOwnershipBuilder.OwnedEntityType.SetIsTableExcludedFromMigrations(excludedFromMigrations); + + if (excludedFromMigrations.HasValue) + { + referenceOwnershipBuilder.OwnedEntityType.SetIsTableExcludedFromMigrations(excludedFromMigrations.Value); + } return referenceOwnershipBuilder; } @@ -300,7 +322,10 @@ public static OwnedNavigationBuilder ToTable (OwnedNavigationBuilder)ToTable( - (OwnedNavigationBuilder)referenceOwnershipBuilder, name, schema, excludedFromMigrations: false); + referenceOwnershipBuilder, name, schema, excludedFromMigrations: + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue23137", out var isEnabled) && isEnabled + ? false + : (bool?)null); /// /// Configures the table that the entity type maps to when targeting a relational database. diff --git a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs index 00ed23c10b6..b82b4d3f821 100644 --- a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs @@ -833,7 +833,8 @@ public static bool IsTableExcludedFromMigrations([NotNull] this IEntityType enti return excluded.Value; } - if (entityType.FindAnnotation(RelationalAnnotationNames.TableName) != null) + var useOldBehavior = AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue23137", out var isEnabled) && isEnabled; + if (useOldBehavior && entityType.FindAnnotation(RelationalAnnotationNames.TableName) != null) { return false; } diff --git a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs index ed91236f62e..f3b8c7a8dc0 100644 --- a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs +++ b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs @@ -1340,6 +1340,12 @@ protected virtual IEnumerable Remove([NotNull] IForeignKeyCo { var sourceTable = source.Table; + var useOldBehavior = AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue23137", out var isEnabled) && isEnabled; + if (!useOldBehavior && sourceTable.IsExcludedFromMigrations) + { + yield break; + } + var dropTableOperation = diffContext.FindDrop(sourceTable); if (dropTableOperation == null) { @@ -2173,7 +2179,10 @@ private IEnumerable GetDataOperations( InsertDataOperation batchInsertOperation = null; foreach (var command in commandBatch.ModificationCommands) { - if (diffContext.FindDrop(model.FindTable(command.TableName, command.Schema)) != null) + var table = model.FindTable(command.TableName, command.Schema); + var useOldBehavior = AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue23137", out var isEnabled) && isEnabled; + if (diffContext.FindDrop(table) != null + || (!useOldBehavior && table.IsExcludedFromMigrations)) { continue; } @@ -2269,8 +2278,6 @@ private IEnumerable GetDataOperations( break; } - var table = command.Entries.First().EntityType.GetTableMappings().Select(m => m.Table) - .First(t => t.Name == command.TableName && t.Schema == command.Schema); var keyColumns = command.ColumnModifications.Where(col => col.IsKey) .Select(c => table.FindColumn(c.ColumnName)); var anyKeyColumnDropped = keyColumns.Any(c => diffContext.FindDrop(c) != null); diff --git a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs index c0d21dc31c0..9a13edb71a4 100644 --- a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs +++ b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs @@ -1949,6 +1949,7 @@ public virtual void Owned_types_are_stored_in_snapshot() Assert.Null(owned1index2.GetFilter()); Assert.Equal(new object[] { 1, -1 }, ownedType1.GetSeedData().Single().Values); Assert.Equal(nameof(EntityWithOneProperty), ownedType1.GetTableName()); + Assert.False(ownedType1.IsTableExcludedFromMigrations()); var entityWithStringKey = o.FindEntityType(typeof(EntityWithStringKey)); Assert.Same( @@ -1973,6 +1974,233 @@ public virtual void Owned_types_are_stored_in_snapshot() Assert.False(owned2index2.IsUnique); Assert.Null(owned2index2.GetFilter()); Assert.Equal(nameof(EntityWithStringProperty), ownedType2.GetTableName()); + Assert.False(ownedType2.IsTableExcludedFromMigrations()); + + Assert.Same(entityWithOneProperty, ownedType2.GetNavigations().Single().TargetEntityType); + }); + } + + [ConditionalFact] + public virtual void Owned_types_are_stored_in_snapshot_when_excluded() + { + Test( + builder => + { + builder.Entity( + b => + { + b.HasKey(e => e.Id).HasName("PK_Custom"); + + b.OwnsOne( + eo => eo.EntityWithTwoProperties, eb => + { + eb.HasKey(e => e.AlternateId).HasName("PK_Custom"); + eb.WithOwner(e => e.EntityWithOneProperty) + .HasForeignKey(e => e.AlternateId) + .HasConstraintName("FK_Custom"); + eb.HasIndex(e => e.Id); + + eb.HasOne(e => e.EntityWithStringKey).WithOne(); + + eb.HasData( + new EntityWithTwoProperties { AlternateId = 1, Id = -1 }); + }); + + b.HasData( + new EntityWithOneProperty { Id = 1 }); + + b.ToTable("EntityWithOneProperty", e => e.ExcludeFromMigrations()); + }); + + builder.Entity( + b => { + b.OwnsMany( + es => es.Properties, es => + { + es.HasKey(e => e.Id); + es.HasOne(e => e.EntityWithOneProperty).WithOne(); + + es.ToTable("EntityWithStringProperty", excludedFromMigrations: true); + }); + + b.ToTable("EntityWithStringKey", e => e.ExcludeFromMigrations()); + }); + }, + AddBoilerPlate( + GetHeading() + + @" + modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithOneProperty"", b => + { + b.Property(""Id"") + .ValueGeneratedOnAdd() + .HasColumnType(""int"") + .UseIdentityColumn(); + + b.HasKey(""Id"") + .HasName(""PK_Custom""); + + b.ToTable(""EntityWithOneProperty"", t => t.ExcludeFromMigrations()); + + b.HasData( + new + { + Id = 1 + }); + }); + + modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringKey"", b => + { + b.Property(""Id"") + .HasColumnType(""nvarchar(450)""); + + b.HasKey(""Id""); + + b.ToTable(""EntityWithStringKey"", t => t.ExcludeFromMigrations()); + }); + + modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithOneProperty"", b => + { + b.OwnsOne(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithTwoProperties"", ""EntityWithTwoProperties"", b1 => + { + b1.Property(""AlternateId"") + .ValueGeneratedOnAdd() + .HasColumnType(""int"") + .UseIdentityColumn(); + + b1.Property(""EntityWithStringKeyId"") + .HasColumnType(""nvarchar(450)""); + + b1.Property(""Id"") + .HasColumnType(""int""); + + b1.HasKey(""AlternateId"") + .HasName(""PK_Custom""); + + b1.HasIndex(""EntityWithStringKeyId"") + .IsUnique() + .HasFilter(""[EntityWithTwoProperties_EntityWithStringKeyId] IS NOT NULL""); + + b1.HasIndex(""Id""); + + b1.ToTable(""EntityWithOneProperty""); + + b1.WithOwner(""EntityWithOneProperty"") + .HasForeignKey(""AlternateId"") + .HasConstraintName(""FK_Custom""); + + b1.HasOne(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringKey"", ""EntityWithStringKey"") + .WithOne() + .HasForeignKey(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithTwoProperties"", ""EntityWithStringKeyId""); + + b1.Navigation(""EntityWithOneProperty""); + + b1.Navigation(""EntityWithStringKey""); + + b1.HasData( + new + { + AlternateId = 1, + Id = -1 + }); + }); + + b.Navigation(""EntityWithTwoProperties""); + }); + + modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringKey"", b => + { + b.OwnsMany(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringProperty"", ""Properties"", b1 => + { + b1.Property(""Id"") + .ValueGeneratedOnAdd() + .HasColumnType(""int"") + .UseIdentityColumn(); + + b1.Property(""EntityWithOnePropertyId"") + .HasColumnType(""int""); + + b1.Property(""EntityWithStringKeyId"") + .IsRequired() + .HasColumnType(""nvarchar(450)""); + + b1.Property(""Name"") + .HasColumnType(""nvarchar(max)""); + + b1.HasKey(""Id""); + + b1.HasIndex(""EntityWithOnePropertyId"") + .IsUnique() + .HasFilter(""[EntityWithOnePropertyId] IS NOT NULL""); + + b1.HasIndex(""EntityWithStringKeyId""); + + b1.ToTable(""EntityWithStringProperty"", excludedFromMigrations: true); + + b1.HasOne(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithOneProperty"", ""EntityWithOneProperty"") + .WithOne() + .HasForeignKey(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringProperty"", ""EntityWithOnePropertyId""); + + b1.WithOwner() + .HasForeignKey(""EntityWithStringKeyId""); + + b1.Navigation(""EntityWithOneProperty""); + }); + + b.Navigation(""Properties""); + });", usingSystem: true), + o => + { + var entityWithOneProperty = o.FindEntityType(typeof(EntityWithOneProperty)); + Assert.Equal("PK_Custom", entityWithOneProperty.GetKeys().Single().GetName()); + Assert.Equal(new object[] { 1 }, entityWithOneProperty.GetSeedData().Single().Values); + + var ownership1 = entityWithOneProperty.FindNavigation(nameof(EntityWithOneProperty.EntityWithTwoProperties)) + .ForeignKey; + Assert.Equal(nameof(EntityWithTwoProperties.AlternateId), ownership1.Properties[0].Name); + Assert.Equal(nameof(EntityWithTwoProperties.EntityWithOneProperty), ownership1.DependentToPrincipal.Name); + Assert.True(ownership1.IsRequired); + Assert.Equal("FK_Custom", ownership1.GetConstraintName()); + var ownedType1 = ownership1.DeclaringEntityType; + Assert.Equal(nameof(EntityWithTwoProperties.AlternateId), ownedType1.FindPrimaryKey().Properties[0].Name); + Assert.Equal("PK_Custom", ownedType1.GetKeys().Single().GetName()); + Assert.Equal(2, ownedType1.GetIndexes().Count()); + var owned1index1 = ownedType1.GetIndexes().First(); + Assert.Equal("EntityWithStringKeyId", owned1index1.Properties[0].Name); + Assert.True(owned1index1.IsUnique); + Assert.Equal("[EntityWithTwoProperties_EntityWithStringKeyId] IS NOT NULL", owned1index1.GetFilter()); + var owned1index2 = ownedType1.GetIndexes().Last(); + Assert.Equal("Id", owned1index2.Properties[0].Name); + Assert.False(owned1index2.IsUnique); + Assert.Null(owned1index2.GetFilter()); + Assert.Equal(new object[] { 1, -1 }, ownedType1.GetSeedData().Single().Values); + Assert.Equal(nameof(EntityWithOneProperty), ownedType1.GetTableName()); + Assert.True(ownedType1.IsTableExcludedFromMigrations()); + + var entityWithStringKey = o.FindEntityType(typeof(EntityWithStringKey)); + Assert.Same( + entityWithStringKey, + ownedType1.FindNavigation(nameof(EntityWithTwoProperties.EntityWithStringKey)).TargetEntityType); + Assert.Equal(nameof(EntityWithStringKey), entityWithStringKey.GetTableName()); + Assert.True(entityWithStringKey.IsTableExcludedFromMigrations()); + + var ownership2 = entityWithStringKey.FindNavigation(nameof(EntityWithStringKey.Properties)).ForeignKey; + Assert.Equal("EntityWithStringKeyId", ownership2.Properties[0].Name); + Assert.Null(ownership2.DependentToPrincipal); + Assert.True(ownership2.IsRequired); + var ownedType2 = ownership2.DeclaringEntityType; + Assert.Equal(nameof(EntityWithStringProperty.Id), ownedType2.FindPrimaryKey().Properties[0].Name); + Assert.Single(ownedType2.GetKeys()); + Assert.Equal(2, ownedType2.GetIndexes().Count()); + var owned2index1 = ownedType2.GetIndexes().First(); + Assert.Equal("EntityWithOnePropertyId", owned2index1.Properties[0].Name); + Assert.True(owned2index1.IsUnique); + Assert.Equal("[EntityWithOnePropertyId] IS NOT NULL", owned2index1.GetFilter()); + var owned2index2 = ownedType2.GetIndexes().Last(); + Assert.Equal("EntityWithStringKeyId", owned2index2.Properties[0].Name); + Assert.False(owned2index2.IsUnique); + Assert.Null(owned2index2.GetFilter()); + Assert.Equal(nameof(EntityWithStringProperty), ownedType2.GetTableName()); + Assert.True(ownedType2.IsTableExcludedFromMigrations()); Assert.Same(entityWithOneProperty, ownedType2.GetNavigations().Single().TargetEntityType); }); diff --git a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs index 8cae27110a7..7d2db69d25a 100644 --- a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs +++ b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs @@ -9628,6 +9628,105 @@ public void SeedData_type_with_owned_collection_no_changes() skipSourceConventions: true); } + [ConditionalFact] + public void SeedData_type_with_excluded_owned_collection() + { + Execute( + common => + { + common.Entity( + c => + { + c.Ignore(x => x.Mailing); + + c.HasKey(x => x.Id); + c.HasData(new Customer { Id = 1 }); + + c.OwnsMany( + y => y.Orders, x => + { + x.Ignore(o => o.Billing); + x.Ignore(o => o.Shipping); + + x.WithOwner() + .HasForeignKey("CustomerId"); + + x.HasKey("CustomerId", "Id"); + x.HasData(new { Id = 2, CustomerId = 1 }); + }); + }); + }, + _ => { }, + target => { + target.Entity( + c => + { + c.OwnsMany( + y => y.Orders, x => + { + x.ToTable("Order", excludedFromMigrations: true); + }); + c.ToTable("Customer", t => t.ExcludeFromMigrations()); + }); + }, + Assert.Empty, + Assert.Empty, + skipSourceConventions: true); + } + + [ConditionalFact] + public void SeedData_type_with_owned_collection_excluded() + { + Execute( + common => + { + common.Entity( + c => + { + c.Ignore(x => x.Mailing); + + c.HasKey(x => x.Id); + c.HasData(new Customer { Id = 1 }); + + c.OwnsMany( + y => y.Orders, x => + { + x.Ignore(o => o.Billing); + x.Ignore(o => o.Shipping); + + x.WithOwner() + .HasForeignKey("CustomerId"); + + x.HasKey("CustomerId", "Id"); + x.HasData(new { Id = 2, CustomerId = 1 }); + + x.ToTable("Order", excludedFromMigrations: true); + }); + + c.ToTable("Customer", t => t.ExcludeFromMigrations()); + }); + }, + _ => { }, + _ => { }, + Assert.Empty, + Assert.Empty, + skipSourceConventions: true); + } + + public class Parent + { + public Guid Id { get; set; } + public string Name { get; set; } + + public IEnumerable Children { get; set; } + } + + public class Child + { + public Guid Id { get; set; } + public string ChildName { get; set; } + } + [ConditionalFact] public void Old_style_ownership_to_new_style() { diff --git a/test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderGenericTestBase.cs b/test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderGenericTestBase.cs new file mode 100644 index 00000000000..5759b9c3070 --- /dev/null +++ b/test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderGenericTestBase.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +// ReSharper disable InconsistentNaming +namespace Microsoft.EntityFrameworkCore.ModelBuilding +{ + public class RelationalModelBuilderTest : ModelBuilderTest + { + public abstract class TestTableBuilder + where TEntity : class + { + public abstract TestTableBuilder ExcludeFromMigrations(bool excluded = true); + } + + public class GenericTestTableBuilder : TestTableBuilder + where TEntity : class + { + public GenericTestTableBuilder(TableBuilder tableBuilder) + { + TableBuilder = tableBuilder; + } + + protected TableBuilder TableBuilder { get; } + + protected virtual TestTableBuilder Wrap(TableBuilder tableBuilder) + => new GenericTestTableBuilder(tableBuilder); + + public override TestTableBuilder ExcludeFromMigrations(bool excluded = true) + => Wrap(TableBuilder.ExcludeFromMigrations(excluded)); + } + + public class NonGenericTestTableBuilder : TestTableBuilder + where TEntity : class + { + public NonGenericTestTableBuilder(TableBuilder tableBuilder) + { + TableBuilder = tableBuilder; + } + + protected TableBuilder TableBuilder { get; } + + protected virtual TestTableBuilder Wrap(TableBuilder tableBuilder) + => new NonGenericTestTableBuilder(tableBuilder); + + public override TestTableBuilder ExcludeFromMigrations(bool excluded = true) + => Wrap(TableBuilder.ExcludeFromMigrations(excluded)); + } + } +} diff --git a/test/EFCore.Relational.Tests/ModelBuilding/RelationalTestModelBuilderExtensions.cs b/test/EFCore.Relational.Tests/ModelBuilding/RelationalTestModelBuilderExtensions.cs index d93bf3aefa6..fcfb50bd886 100644 --- a/test/EFCore.Relational.Tests/ModelBuilding/RelationalTestModelBuilderExtensions.cs +++ b/test/EFCore.Relational.Tests/ModelBuilding/RelationalTestModelBuilderExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -147,6 +148,49 @@ public static ModelBuilderTest.TestEntityTypeBuilder ToTable( return builder; } + public static ModelBuilderTest.TestEntityTypeBuilder ToTable( + this ModelBuilderTest.TestEntityTypeBuilder builder, + string name, + Action> buildAction) + where TEntity : class + { + switch (builder) + { + case IInfrastructure> genericBuilder: + genericBuilder.Instance.ToTable(name, + b => buildAction(new RelationalModelBuilderTest.GenericTestTableBuilder(b))); + break; + case IInfrastructure nongenericBuilder: + nongenericBuilder.Instance.ToTable(name, + b => buildAction(new RelationalModelBuilderTest.NonGenericTestTableBuilder(b))); + break; + } + + return builder; + } + + public static ModelBuilderTest.TestEntityTypeBuilder ToTable( + this ModelBuilderTest.TestEntityTypeBuilder builder, + string name, + string schema, + Action> buildAction) + where TEntity : class + { + switch (builder) + { + case IInfrastructure> genericBuilder: + genericBuilder.Instance.ToTable(name, schema, + b => buildAction(new RelationalModelBuilderTest.GenericTestTableBuilder(b))); + break; + case IInfrastructure nongenericBuilder: + nongenericBuilder.Instance.ToTable(name, schema, + b => buildAction(new RelationalModelBuilderTest.NonGenericTestTableBuilder(b))); + break; + } + + return builder; + } + public static ModelBuilderTest.TestOwnedNavigationBuilder ToTable( this ModelBuilderTest.TestOwnedNavigationBuilder builder, string name) @@ -186,6 +230,47 @@ public static ModelBuilderTest.TestOwnedNavigationBuilder ToTable( + this ModelBuilderTest.TestOwnedNavigationBuilder builder, + string name, + bool excludedFromMigrations) + where TEntity : class + where TRelatedEntity : class + { + switch (builder) + { + case IInfrastructure> genericBuilder: + genericBuilder.Instance.ToTable(name, excludedFromMigrations); + break; + case IInfrastructure nongenericBuilder: + nongenericBuilder.Instance.ToTable(name, excludedFromMigrations); + break; + } + + return builder; + } + + public static ModelBuilderTest.TestOwnedNavigationBuilder ToTable( + this ModelBuilderTest.TestOwnedNavigationBuilder builder, + string name, + string schema, + bool excludedFromMigrations) + where TEntity : class + where TRelatedEntity : class + { + switch (builder) + { + case IInfrastructure> genericBuilder: + genericBuilder.Instance.ToTable(name, schema, excludedFromMigrations); + break; + case IInfrastructure nongenericBuilder: + nongenericBuilder.Instance.ToTable(name, schema, excludedFromMigrations); + break; + } + + return builder; + } + public static ModelBuilderTest.TestOwnershipBuilder HasConstraintName( this ModelBuilderTest.TestOwnershipBuilder builder, string name) diff --git a/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs b/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs index 5929f551921..019e804db33 100644 --- a/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs +++ b/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs @@ -439,7 +439,7 @@ public virtual void Owned_types_can_be_mapped_to_different_tables() modelBuilder.Entity( bb => { - bb.ToTable("BT", "BS"); + bb.ToTable("BT", "BS", t => t.ExcludeFromMigrations()); bb.OwnsOne( b => b.AlternateLabel, tb => { @@ -452,7 +452,7 @@ public virtual void Owned_types_can_be_mapped_to_different_tables() l => l.AnotherBookLabel, ab => { ab.Ignore(l => l.Book); - ab.ToTable("AT1", "AS1"); + ab.ToTable("AT1", "AS1", excludedFromMigrations: false); ab.OwnsOne(s => s.SpecialBookLabel) .ToTable("ST11", "SS11") .Ignore(l => l.Book) @@ -520,18 +520,22 @@ public virtual void Owned_types_can_be_mapped_to_different_tables() Assert.Equal("BS", book.GetSchema()); Assert.Equal("BT", book.GetTableName()); + Assert.True(book.IsTableExcludedFromMigrations()); Assert.Equal("LS", bookOwnership1.DeclaringEntityType.GetSchema()); Assert.Equal("LT", bookOwnership1.DeclaringEntityType.GetTableName()); Assert.False(bookOwnership1.DeclaringEntityType.IsMemoryOptimized()); + Assert.True(bookOwnership1.DeclaringEntityType.IsTableExcludedFromMigrations()); Assert.Equal("TS", bookOwnership2.DeclaringEntityType.GetSchema()); Assert.Equal("TT", bookOwnership2.DeclaringEntityType.GetTableName()); Assert.True(bookOwnership2.DeclaringEntityType.IsMemoryOptimized()); + Assert.True(bookOwnership2.DeclaringEntityType.IsTableExcludedFromMigrations()); Assert.Equal("AS2", bookLabel1Ownership1.DeclaringEntityType.GetSchema()); Assert.Equal("AT2", bookLabel1Ownership1.DeclaringEntityType.GetTableName()); Assert.Equal("SS1", bookLabel1Ownership2.DeclaringEntityType.GetSchema()); Assert.Equal("ST1", bookLabel1Ownership2.DeclaringEntityType.GetTableName()); Assert.Equal("AS1", bookLabel2Ownership1.DeclaringEntityType.GetSchema()); Assert.Equal("AT1", bookLabel2Ownership1.DeclaringEntityType.GetTableName()); + Assert.False(bookLabel2Ownership1.DeclaringEntityType.IsTableExcludedFromMigrations()); Assert.Equal("SS2", bookLabel2Ownership2.DeclaringEntityType.GetSchema()); Assert.Equal("ST2", bookLabel2Ownership2.DeclaringEntityType.GetTableName()); Assert.Equal("SS21", bookLabel1Ownership11.DeclaringEntityType.GetSchema());