Несколько внешних ключей Код EF Core 2.1 сначала генерирует только 1 в БД - PullRequest
0 голосов
/ 05 июля 2018

У меня есть следующая модель:

public class User : AuditedModel
{
    public string Login { get; }
    public string PasswordHash { get; }

    public User(string login, string password, User creationUser) : base(creationUser)
    {
        Login = login;
        PasswordHash = GeneratePasswordHash(password);
    }

    protected User(int id, DateTime creationDate, DateTime? terminationDate, string login, string passwordHash) : base(id, 0, creationDate)
    {
        Login = login;
        PasswordHash = passwordHash;
    }
}
public class AuditedModel : BaseModel
{
    protected AuditedModel(User creationUser)
    {
        CreationUser = creationUser;
        CreationDate = DateTime.UtcNow;
    }

    public User CreationUser { get; protected set; }
    public DateTime CreationDate { get; }
    public User TerminationUser { get; protected set; }
    public DateTime? TerminationDate { get; }
}
public class BaseModel
{
    public int Id { get;}

    protected BaseModel()
    {
    }

    public BaseModel(int id)
    {
        Id = id;
    }
}

EF Core Code First должен создать два самоссылающихся внешних ключа для CreationUser и TerminationUser, как указано в Fluent API:

public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable(nameof(User));

        builder.HasKey(u => u.Id);
        builder.Property(u => u.Id).ValueGeneratedOnAdd();

        builder.Property(u => u.Login)
            .IsRequired();

        builder.Property(u => u.PasswordHash);

        builder.Property(u => u.CreationDate);

        builder.Property(u => u.TerminationDate);

        builder.HasOne(u => u.TerminationUser)
            .WithOne()
            .HasForeignKey<User>(u => u.Id)
            .OnDelete(DeleteBehavior.Restrict);

        builder.HasOne(u => u.CreationUser)
            .WithOne()
            .IsRequired()
            .HasForeignKey<User>(u => u.Id)
            .OnDelete(DeleteBehavior.Restrict);
     }
}

Я собираюсь использовать миграции для этого проекта, поэтому я собираюсь показать выходные данные миграции, которые отражаются в базе данных:

public partial class InitialCreate : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.EnsureSchema(
            name: "public");

        migrationBuilder.CreateTable(
            name: "User",
            schema: "public",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
                CreationDate = table.Column<DateTime>(nullable: false),
                TerminationUserId = table.Column<int>(nullable: true),
                TerminationDate = table.Column<DateTime>(nullable: true),
                Login = table.Column<string>(nullable: false),
                PasswordHash = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_User", x => x.Id);
                table.ForeignKey(
                    name: "FK_User_User_TerminationUserId",
                    column: x => x.TerminationUserId,
                    principalSchema: "public",
                    principalTable: "User",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });

        migrationBuilder.CreateIndex(
            name: "IX_User_TerminationUserId",
            schema: "public",
            table: "User",
            column: "TerminationUserId");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "User",
            schema: "public");
    }
}

Как показано, существует только столбец TerminationUserId ForeignKey, даже если для навигации CreationUser установлено обязательное значение.

    I'm using:
    - Npgsql.EntityFrameworkCore.PostgreSQL 2.1.1
    - Microsoft.NETCore.App 2.1.0
    - Microsoft.EntityFrameworkCore.Tools.DotNet 2.0.3
    - Microsoft.EntityFrameworkCore.Design 2.1.1
    - Microsoft.VisualStudio.Web.CodeGeneration.Tools 2.0.4

1 Ответ

0 голосов
/ 05 июля 2018

Я удивлен, что столбец внешнего ключа TerminationUserId создан, поскольку его нет в вашей модели. Если вы хотите, чтобы были созданы оба столбца внешнего ключа, вам нужно добавить их в модель следующим образом:

public class AuditedModel : BaseModel
{
    protected AuditedModel(User creationUser)
    {
        CreationUser = creationUser;
        CreationDate = DateTime.UtcNow;
    }

    public int CreationUserId { get; protected set; }
    public User CreationUser { get; protected set; }
    public DateTime CreationDate { get; }
    public int? TerminationUserId { get; protected set; }
    public User TerminationUser { get; protected set; }
    public DateTime? TerminationDate { get; }
}

А затем в вашем отображении Fluent API:

    builder.HasOne(u => u.TerminationUser)
        .WithOne()
        .HasForeignKey<User>(u => u.TerminationUserId)
        .OnDelete(DeleteBehavior.Restrict);

    builder.HasOne(u => u.CreationUser)
        .WithOne()
        .IsRequired()
        .HasForeignKey<User>(u => u.CreationUserId)
        .OnDelete(DeleteBehavior.Restrict);
...