dotnet / dotnet/efcore

No effect on changing the data seeding when inheriting over 2 DbContexts in the same Database

Open
#32,231 2 comments 0 reactions 1 assignee Claimed by @AndriySvyryd View on GitHub
area-migrations-seeding customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

## Discription

In the following example, I need a persitent base class (e.g. Animals). This is managed with a concrete class (e.g. Monkeys) in a DbContext. the 2nd DbConnext contains a class (e.g. Human) with the same base class (e.g. Monkeys). With inital data seeding, everything works. But if I make a record after the initial data seeding, the record is suppressed.

### Code from Animals Project with expected results
```C#
namespace Animals
{
public abstract class Animal
{
[Key]
public int Id { get; set; }
public virtual int? Height { get; set; }
public virtual int? Weight { get; set; }
}
public class Monkey : Animal
{
}

public class AnimalContext : DbContext
{
public AnimalContext(DbContextOptions options) : base(options)
{
}

public DbSet Animals { get; set; }
public DbSet Monkeys { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity()
.ToTable("Animal")
.HasDiscriminator("ClassType")
.HasValue(0)
.HasValue(1);
modelBuilder.Entity().ToTable("Animal");

modelBuilder.Entity().HasData(
new Monkey { Id=1, Height = 100, Weight = 20 },
new Monkey { Id=2, Height = 120, Weight = 30 }
);
}
}

public class AnimalContextFactory : IDesignTimeDbContextFactory
{
public AnimalContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(
"Integrated Security=SSPI;Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=Test",
b => b.MigrationsAssembly("Animals").MigrationsHistoryTable("AnimalMigration"));
optionsBuilder.EnableSensitiveDataLogging();
return new AnimalContext(optionsBuilder.Options);
}
}
}
```
PS> dotnet ef migrations add Init --project Animals
```C#
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Animal",
columns: table => new
{
Id = table.Column(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Height = table.Column(type: "int", nullable: true),
Weight = table.Column(type: "int", nullable: true),
ClassType = table.Column(type: "tinyint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Animal", x => x.Id);
});

migrationBuilder.InsertData(
table: "Animal",
columns: new[] { "Id", "ClassType", "Height", "Weight" },
values: new object[,]
{
{ 1, (byte)1, 100, 20 },
{ 2, (byte)1, 120, 30 }
});
}
```
### Code from Human Project with expected results
```C#
namespace Humans
{
public class Human : Monkey
{
}

public class HumanContext : DbContext
{
public HumanContext(DbContextOptions options) : base(options)
{
}

public DbSet Animals { get; set; }
public DbSet Monkeys { get; set; }
public DbSet Human { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity()
.ToTable("Animal")
.HasDiscriminator("ClassType")
.HasValue(0)
.HasValue(1)
.HasValue(2);
modelBuilder.Entity().ToTable("Animal");
modelBuilder.Entity().ToTable("Animal");

modelBuilder.Entity().Metadata.SetIsTableExcludedFromMigrations(true);
modelBuilder.Entity().Metadata.SetIsTableExcludedFromMigrations(true);

modelBuilder.Entity().HasData(
new Human { Id = 100, Height = 160, Weight = 70 },
new Human { Id = 101, Height = 179, Weight = 80 }
// ,new Human { Id = 102, Height = 180, Weight = 85 } // Missing after the inital data seeding
);
}
}

public class HumanContextFactory : IDesignTimeDbContextFactory
{
public HumanContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(
"Integrated Security=SSPI;Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=Test",
b => b.MigrationsAssembly("Humans").MigrationsHistoryTable("HumanMigration"));
optionsBuilder.EnableSensitiveDataLogging();
return new HumanContext(optionsBuilder.Options);
}
}
}
```
PS> dotnet ef migrations add Init --project Human
```C#
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "Animal",
columns: new[] { "Id", "ClassType", "Height", "Weight" },
values: new object[,]
{
{ 100, (byte)2, 160, 70 },
{ 101, (byte)2, 179, 80 }
});
}
```
### Code in Project Human with unexpected result (BUG)
```C#
public class HumanContext : DbContext
{
public HumanContext(DbContextOptions options) : base(options)
{
}

public DbSet Animals { get; set; }
public DbSet Monkeys { get; set; }
public DbSet Human { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity()
.ToTable("Animal")
.HasDiscriminator("ClassType")
.HasValue(0)
.HasValue(1)
.HasValue(2);
modelBuilder.Entity().ToTable("Animal");
modelBuilder.Entity().ToTable("Animal");

modelBuilder.Entity().Metadata.SetIsTableExcludedFromMigrations(true);
modelBuilder.Entity().Metadata.SetIsTableExcludedFromMigrations(true);

modelBuilder.Entity().HasData(
new Human { Id = 100, Height = 160, Weight = 70 },
new Human { Id = 101, Height = 179, Weight = 80 }
,new Human { Id = 102, Height = 180, Weight = 85 } // Missing after the inital data seeding
);
}
}
```
PS> dotnet ef migrations add Human102 --project Human
```C#
protected override void Up(MigrationBuilder migrationBuilder)
{

}
```
### Include provider and version information

EF Core version: 7.0.13
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: NET 7.0
Operating system: IDE: Visual Studio 2022 17.7.5

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.