efcore
efcore copied to clipboard
Explicit configuration of a TPT relationship causes the database constraint not to be created
Consider the simple TPT model:
[Table("FeaturedPosts")]
public class FeaturedPost : Post
{
}
[Table("Posts")]
public class Post
{
public int Id { get; set; }
public string? Title { get; set; }
public string? Content { get; set; }
}
This results in the following tables:
CREATE TABLE [Posts] (
[Id] int NOT NULL IDENTITY,
[Title] nvarchar(max) NULL,
[Content] nvarchar(max) NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([Id])
);
CREATE TABLE [FeaturedPosts] (
[Id] int NOT NULL,
CONSTRAINT [PK_FeaturedPosts] PRIMARY KEY ([Id]),
CONSTRAINT [FK_FeaturedPosts_Posts_Id] FOREIGN KEY ([Id]) REFERENCES [Posts] ([Id]) ON DELETE CASCADE
);
I want to change the cascade behavior for the FK constraint between the two tables, so I do this:
modelBuilder
.Entity<Post>()
.HasOne<FeaturedPost>()
.WithOne()
.HasForeignKey<FeaturedPost>(e => e.Id)
.OnDelete(DeleteBehavior.ClientCascade);
Now the FK constraint disappears entirely!
CREATE TABLE [FeaturedPosts] (
[Id] int NOT NULL IDENTITY,
CONSTRAINT [PK_FeaturedPosts] PRIMARY KEY ([Id])
);
CREATE TABLE [Posts] (
[Id] int NOT NULL IDENTITY,
[Title] nvarchar(max) NULL,
[Content] nvarchar(max) NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([Id])
);
Full code:
[Table("FeaturedPosts")]
public class FeaturedPost : Post
{
}
[Table("Posts")]
public class Post
{
public int Id { get; set; }
public string? Title { get; set; }
public string? Content { get; set; }
}
public class SomeDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(Your.ConnectionString)
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Post>()
.HasOne<FeaturedPost>()
.WithOne()
.HasForeignKey<FeaturedPost>(e => e.Id)
.OnDelete(DeleteBehavior.ClientCascade);
modelBuilder.Entity<FeaturedPost>();
}
}
public class Program
{
public static void Main()
{
using (var context = new SomeDbContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
context.Add(new Post());
context.Add(new FeaturedPost());
context.SaveChanges();
}
using (var context = new SomeDbContext())
{
foreach (var post in context.Set<Post>().ToList())
{
Console.WriteLine(post.GetType());
}
}
}
}