dotnet / dotnet/efcore

Explicit configuration of a TPT relationship causes the database constraint not to be created

Open
#29,169 2 comments 0 reactions 0 assignees View on GitHub
area-model-building
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

Consider the simple TPT model:

```C#
[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:

```sql
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:

```C#
modelBuilder
.Entity()
.HasOne()
.WithOne()
.HasForeignKey(e => e.Id)
.OnDelete(DeleteBehavior.ClientCascade);
```

Now the FK constraint disappears entirely!

```sql
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:

```C#
[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()
.HasOne()
.WithOne()
.HasForeignKey(e => e.Id)
.OnDelete(DeleteBehavior.ClientCascade);

modelBuilder.Entity();
}
}

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().ToList())
{
Console.WriteLine(post.GetType());
}
}
}
}
```

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.