ARTICLE AD BOX
We are using .NET 10 and the following NuGet packages:
Microsoft.EntityFrameworkCore 10.0.3 Microsoft.EntityFrameworkCore.Design 10.0.3 Npgsql.EntityFrameworkCore.PostgreSQL 10.0.0We have a simple PostgreSQL database which contains 2 tables: trgt.target and trgt.target_request. One target can have multiple target requests, but only one of them can be active at a time (unique index ux_target_request_active_per_target).
-- 1. create schema create schema if not exists trgt; -- 2. create table trgt.target create table trgt.target ( id serial primary key, name varchar(255) not null ); -- 3. create table trgt.target_request create table trgt.target_request ( id serial primary key, target_id integer not null, is_active boolean not null, constraint fk_target_request_target foreign key (target_id) references trgt.target(id) on delete cascade ); -- 4. ensure only one active request per target create unique index ux_target_request_active_per_target on trgt.target_request (target_id) where is_active = true;We are using database first approach - we scaffold the DB tables into C# models. We use the following command to scaffold the trgt schema:
dotnet ef dbcontext scaffold "Host=localhost;Database=UniqueIndexScaffold;Username=postgres;Password=postgres" Npgsql.EntityFrameworkCore.PostgreSQL -c TrgtDbContext -o Models --schema trgt --force --verbose --data-annotations --no-onconfiguringThe scaffolded TrgtDbContext.cs has the following content:
public partial class TrgtDbContext : DbContext { public TrgtDbContext(DbContextOptions<TrgtDbContext> options) : base(options) { } public virtual DbSet<Target> Targets { get; set; } public virtual DbSet<TargetRequest> TargetRequests { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Target>(entity => { entity.HasKey(e => e.Id).HasName("target_pkey"); }); modelBuilder.Entity<TargetRequest>(entity => { entity.HasKey(e => e.Id).HasName("target_request_pkey"); entity.HasIndex(e => e.TargetId, "ux_target_request_active_per_target") .IsUnique() .HasFilter("(is_active = true)"); entity.HasOne(d => d.Target).WithOne(p => p.TargetRequest).HasConstraintName("fk_target_request_target"); }); OnModelCreatingPartial(modelBuilder); } partial void OnModelCreatingPartial(ModelBuilder modelBuilder); }The scaffolded Target.cs file has the following content:
[Table("target", Schema = "trgt")] public partial class Target { [Key] [Column("id")] public int Id { get; set; } [Column("name")] [StringLength(255)] public string Name { get; set; } = null!; [InverseProperty("Target")] public virtual TargetRequest? TargetRequest { get; set; } }We find it strange that it contains the property public virtual TargetRequest? TargetRequest. Although we have a unique index ux_target_request_active_per_target which allows only one active target request per target, the target can still have multiple inactive target requests.
If we remove the ux_target_request_active_per_target unique index and scaffold the database again, the Target.cs contains a property public virtual ICollection<TargetRequest> TargetRequests, which is expected. We would also expect this exacty property to be present when the index ux_target_request_active_per_target exists.
Is this a bug in the scaffolder? Are there any workarounds?
