Skip to content

Commit

Permalink
Store null table name in the model snapshot for TPC abstract types (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers committed Feb 13, 2023
1 parent c201f2a commit 9ef3afe
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,7 @@ private void GenerateTableMapping(

var explicitName = tableNameAnnotation != null
|| entityType.BaseType == null
|| (entityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy && entityType.IsAbstract())
|| entityType.BaseType.GetTableName() != tableName
|| hasOverrides;

Expand Down
201 changes: 201 additions & 0 deletions test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,34 @@ public override bool GeneratesTemporaryValues
=> false;
}

private abstract class Animal
{
public int Id { get; set; }
public string Name { get; set; }
}

private abstract class Pet : Animal
{
public string Vet { get; set; }
public ICollection<Human> Humans { get; } = new List<Human>();
}

private class Cat : Pet
{
public string EducationLevel { get; set; }
}

private class Dog : Pet
{
public string FavoriteToy { get; set; }
}

private class Human : Animal
{
public Animal FavoriteAnimal { get; set; }
public ICollection<Pet> Pets { get; } = new List<Pet>();
}

#region Model

[ConditionalFact]
Expand Down Expand Up @@ -739,6 +767,179 @@ public virtual void Entities_are_stored_in_model_snapshot_for_TPC()
Assert.Equal("DerivedView", derived.GetViewName());
});

[ConditionalFact] // Issue #30058
public virtual void Non_base_abstract_base_class_with_TPC()
=> Test(
builder =>
{
builder.Entity<Animal>().UseTpcMappingStrategy();
builder.Entity<Pet>();
builder.Entity<Cat>();
builder.Entity<Dog>();
builder.Entity<Human>();
},
"""
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace RootNamespace
{
[DbContext(typeof(DbContext))]
partial class Snapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("DefaultSchema")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.HasSequence("AnimalSequence");
modelBuilder.Entity("HumanPet", b =>
{
b.Property<int>("HumansId")
.HasColumnType("int");
b.Property<int>("PetsId")
.HasColumnType("int");
b.HasKey("HumansId", "PetsId");
b.HasIndex("PetsId");
b.ToTable("HumanPet", "DefaultSchema");
});
modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Animal", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasDefaultValueSql("NEXT VALUE FOR [DefaultSchema].[AnimalSequence]");
SqlServerPropertyBuilderExtensions.UseSequence(b.Property<int>("Id"));
b.Property<string>("Name")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable((string)null);
b.UseTpcMappingStrategy();
});
modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Human", b =>
{
b.HasBaseType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Animal");
b.Property<int?>("FavoriteAnimalId")
.HasColumnType("int");
b.HasIndex("FavoriteAnimalId");
b.ToTable("Human", "DefaultSchema");
});
modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Pet", b =>
{
b.HasBaseType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Animal");
b.Property<string>("Vet")
.HasColumnType("nvarchar(max)");
b.ToTable((string)null);
});
modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Cat", b =>
{
b.HasBaseType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Pet");
b.Property<string>("EducationLevel")
.HasColumnType("nvarchar(max)");
b.ToTable("Cat", "DefaultSchema");
});
modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Dog", b =>
{
b.HasBaseType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Pet");
b.Property<string>("FavoriteToy")
.HasColumnType("nvarchar(max)");
b.ToTable("Dog", "DefaultSchema");
});
modelBuilder.Entity("HumanPet", b =>
{
b.HasOne("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Human", null)
.WithMany()
.HasForeignKey("HumansId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Pet", null)
.WithMany()
.HasForeignKey("PetsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Human", b =>
{
b.HasOne("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Animal", "FavoriteAnimal")
.WithMany()
.HasForeignKey("FavoriteAnimalId");
b.Navigation("FavoriteAnimal");
});
#pragma warning restore 612, 618
}
}
}
""",
model =>
{
Assert.Equal(6, model.GetAnnotations().Count());
Assert.Equal(6, model.GetEntityTypes().Count());

var animalType = model.FindEntityType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Animal");
Assert.Null(animalType.GetTableName());
Assert.Null(animalType.GetViewName());
Assert.Equal("TPC", animalType.GetMappingStrategy());

var petType = model.FindEntityType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Pet");
Assert.Null(petType.GetTableName());
Assert.Null(petType.GetViewName());

var catType = model.FindEntityType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Cat");
Assert.Equal("Cat", catType.GetTableName());
Assert.Null(catType.GetViewName());

var dogType = model.FindEntityType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Dog");
Assert.Equal("Dog", dogType.GetTableName());
Assert.Null(dogType.GetViewName());

var humanType = model.FindEntityType("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+Human");
Assert.Equal("Human", humanType.GetTableName());
Assert.Null(humanType.GetViewName());

var humanPetType = model.FindEntityType("HumanPet");
Assert.Equal("HumanPet", humanPetType.GetTableName());
Assert.Null(humanPetType.GetViewName());
});

[ConditionalFact]
public virtual void Entity_splitting_is_stored_in_snapshot_with_tables()
=> Test(
Expand Down

0 comments on commit 9ef3afe

Please sign in to comment.