EF Core scaffold — уникальный индекс с условием WHERE создает сопоставление 1:1 вместо 1:nC#

Место общения программистов C#
Ответить
Anonymous
 EF Core scaffold — уникальный индекс с условием WHERE создает сопоставление 1:1 вместо 1:n

Сообщение Anonymous »

Мы используем .NET 10 и следующие пакеты NuGet:
  • Microsoft.EntityFrameworkCore 10.0.3
  • Microsoft.EntityFrameworkCore.Design 10.0.3
  • Npgsql.EntityFrameworkCore.PostgreSQL 10.0.0
У нас есть простая база данных PostgreSQL, содержащая 2 таблицы: trgt.target и trgt.target_request. Одна цель может иметь несколько целевых запросов, но одновременно может быть активен только один из них (уникальный индекс 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;
Мы используем подход «сначала база данных» — мы преобразуем таблицы БД в модели C#. Мы используем следующую команду для формирования схемы trgt:

Код: Выделить всё

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-onconfiguring
Файл TrgtDbContext.cs имеет следующее содержимое:

Код: Выделить всё

public partial class TrgtDbContext : DbContext
{
public TrgtDbContext(DbContextOptions options)
: base(options)
{
}

public virtual DbSet Targets { get; set; }

public virtual DbSet TargetRequests { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id).HasName("target_pkey");
});

modelBuilder.Entity(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);
}
Заготовленный файл Target.cs имеет следующее содержимое:

Код: Выделить всё

[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; }
}
Нам кажется странным, что он содержит свойство public virtual TargetRequest? Целевой запрос. Хотя у нас есть уникальный индекс ux_target_request_active_per_target, который допускает только один активный целевой запрос для каждой цели, цель все равно может иметь несколько неактивных целевых запросов.
Если мы удалим уникальный индекс ux_target_request_active_per_target и снова создадим базу данных, Target.cs будет содержать свойство public virtual ICollection TargetRequests, что и ожидается. Мы также ожидаем, что именно это свойство будет присутствовать, когда индекс ux_target_request_active_per_target существует.
Это ошибка в scaffolder? Есть ли обходные пути?

Подробнее здесь: https://stackoverflow.com/questions/799 ... pping-inst
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»