Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-empty second migration in TPC scheme using inheritance #30058

Closed
amyboose opened this issue Jan 13, 2023 · 1 comment · Fixed by #30257
Closed

Non-empty second migration in TPC scheme using inheritance #30058

amyboose opened this issue Jan 13, 2023 · 1 comment · Fixed by #30257
Assignees
Labels
area-migrations closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported Servicing-approved type-bug
Milestone

Comments

@amyboose
Copy link

amyboose commented Jan 13, 2023

I'm using a bit change example from microsoft documentation "What's new in EF 7":

using Microsoft.EntityFrameworkCore;
using System.Reflection;

namespace EfCoreTpc;
public class Program
{
    public static void Main(params string[] args)
    {
        IHost host = Host.CreateDefaultBuilder()
        .ConfigureServices(services =>
        {
            services.AddDbContext<MyContext>(builder =>
            {
                builder.UseNpgsql("Host=localhost;Port=7435;Database=testdb;Username=admin;Password=testpass");
            });
        })
        .Build();

        host.Run();
    }
}

public abstract class Animal
{
    protected Animal()
    {

    }

    protected Animal(string name)
    {
        Name = name;
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public abstract string Species { get; }

    public Food? Food { get; set; }
}

public abstract class Pet : Animal
{
    protected Pet(string name)
        : base(name)
    {
    }

    public string? Vet { get; set; }

    public ICollection<Human> Humans { get; } = new List<Human>();
}

public class FarmAnimal : Animal
{
    protected FarmAnimal()
        : base()
    {

    }

    public FarmAnimal(string name, string species)
        : base(name)
    {
        Species = species;
    }

    public override string Species { get; }

    [Precision(18, 2)]
    public decimal Value { get; set; }

    public override string ToString()
        => $"Farm animal '{Name}' ({Species}/{Id}) worth {Value:C} eats {Food?.ToString() ?? "<Unknown>"}";
}

public class Cat : Pet
{
    public Cat(string name, string educationLevel)
        : base(name)
    {
        EducationLevel = educationLevel;
    }

    public string EducationLevel { get; set; }
    public override string Species => "Felis catus";

    public override string ToString()
        => $"Cat '{Name}' ({Species}/{Id}) with education '{EducationLevel}' eats {Food?.ToString() ?? "<Unknown>"}";
}

public class Dog : Pet
{
    public Dog(string name, string favoriteToy)
        : base(name)
    {
        FavoriteToy = favoriteToy;
    }

    public string FavoriteToy { get; set; }
    public override string Species => "Canis familiaris";

    public override string ToString()
        => $"Dog '{Name}' ({Species}/{Id}) with favorite toy '{FavoriteToy}' eats {Food?.ToString() ?? "<Unknown>"}";
}

public class Human : Animal
{
    public Human(string name)
        : base(name)
    {
    }

    public override string Species => "Homo sapiens";

    public Animal? FavoriteAnimal { get; set; }
    public ICollection<Pet> Pets { get; } = new List<Pet>();

    public override string ToString()
        => $"Human '{Name}' ({Species}/{Id}) with favorite animal '{FavoriteAnimal?.Name ?? "<Unknown>"}'" +
           $" eats {Food?.ToString() ?? "<Unknown>"}";
}

public class Food
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class MyContext : DbContext
{
    public MyContext(DbContextOptions options)
        : base(options)
    {

    }

    public DbSet<Animal> Animals => Set<Animal>();
    public DbSet<Pet> Pets => Set<Pet>();
    public DbSet<FarmAnimal> FarmAnimals => Set<FarmAnimal>();
    public DbSet<Cat> Cats => Set<Cat>();
    public DbSet<Dog> Dogs => Set<Dog>();
    public DbSet<Human> Humans => Set<Human>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Animal>().UseTpcMappingStrategy();

        modelBuilder.Entity<Animal>(builder =>
        {
            builder
                .Property(p => p.Id)
                .UseHiLo();

            builder
                .Ignore(p => p.Food);

        });

        modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
    }
}

Then I create 2 migrations using:

  1. command "add-migration Init"
  2. command "add-migration t2" (immediatly after first migration)

The second migration must be empty. But I've got non-empty result:

using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace EfCoreTpc.Migrations
{
    /// <inheritdoc />
    public partial class t2 : Migration
    {
        /// <inheritdoc />
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Pet");
        }

        /// <inheritdoc />
        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Pet",
                columns: table => new
                {
                    Id = table.Column<int>(type: "integer", nullable: false),
                    Name = table.Column<string>(type: "text", nullable: false),
                    Vet = table.Column<string>(type: "text", nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Pet", x => x.Id);
                });
        }
    }
}

Provider and version information

EF Core version: 7.0.1
Database provider: Npgsql Entity Framework Core provider for PostgreSQL
Target framework: NET 7.0
Operating system: Windows 10
IDE: Visual Studio 2022 17.4

@amyboose amyboose changed the title Non-empty secong migration in TPC scheme using inheritance Non-empty second migration in TPC scheme using inheritance Jan 13, 2023
@ajcvickers
Copy link
Member

Note for triage: repros with SQL Server and on latest daily. Minimal repro below.

public class Program
{
    public static void Main(params string[] args)
    {
    }
}

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

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

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

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

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

public class MyContext : DbContext
{
    public DbSet<Animal> Animals => Set<Animal>();
    public DbSet<Pet> Pets => Set<Pet>();
    public DbSet<Cat> Cats => Set<Cat>();
    public DbSet<Dog> Dogs => Set<Dog>();
    public DbSet<Human> Humans => Set<Human>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Animal>().UseTpcMappingStrategy();
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer(@"Data Source=(LocalDb)\MSSQLLocalDB;Database=AllTogetherNow")
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-migrations closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported Servicing-approved type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants