Свободный API для сущности с двумя внешними ключами к одной таблице и первичными ключами теневого свойства - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть иерархия классов, которую я хочу сохранить в базе данных с помощью миграций EF Core, но существуют различные усложняющие факторы, которые не позволяют мне понять, что делать.

Вот иерархия классов:

public sealed class Character
{
    private List<Relationship> relationships = new List<Relationship>();

    public string Name { get; set; }
    public ReadOnlyCollection<Relationship> Relationships { get; } 

    public Character()
    {
        Relationships = new ReadOnlyCollection<Relationship>(this.relationships);
    }
}


public class Relationship
{
    public Character FirstCharacter { get; set; }
    public Character SecondCharacter { get; set; }
    public string Name { get; set; }
}

Таким образом, персонаж может иметь различные отношения, которые имеют ссылку на два символа.Внутренняя логика в классе гарантирует, что все Relationships в foo.Relationships всегда имеют ссылку на foo в Relationship.FirstCharacter или Relationship.SecondCharacter.

Одна сложность заключается в том, что я не могу изменить иерархию классов, поэтомуМне нужно использовать только свободный API.Поскольку у персонажа нет свойства Id, они создаются с помощью свойств тени следующим образом:

modelBuilder.Entity<Character>.Property<Guid>("Id")
                              .ValueGeneratedOnAdd()
                              .HasConversion<string>()
                              .HasAnnotation("Key", 0);

Теперь мне нужно как-то выразить, что у персонажа есть много отношений, и что у отношения есть один FirstCharacter, указывающий на символ, и одинSecondCharacter также указывает на персонажа.Я не могу понять, как это сделать.В настоящее время у меня есть следующее:

modelBuilder.Entity<Character>()
    .HasMany(c => c.Relationships)
    .WithOne(r => r.FirstCharacter);

EF жалуется, что у Relationship нет первичного ключа, поэтому я определяю его следующим образом:

modelBuilder.Entity<Relationship>()
            .HasKey("FirstCharacterId", "SecondCharacterId");

(«FirstCharacterId» и «SecondCharacterId» не являютсясвойства, которые существуют, но которые генерируются в Миграции как внешние ключи, поэтому они действительно существуют в этот момент.)

Как ни странно, когда я создаю миграцию с использованием этого, EF генерирует внешний ключ для FirstCharacter И SecondCharacterНесмотря на то, что WithOne () указывает только на FirstCharacter:

migrationBuilder.CreateTable(
    name: "Relationship",
    columns: table => new
    {
        FirstCharacterId = table.Column<string>(nullable: false),
        SecondCharacterId = table.Column<string>(nullable: false),
        Name = table.Column<string>(nullable: true)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Relationship", x => new { x.FirstCharacterId, x.SecondCharacterId });
        table.ForeignKey(
            name: "FK_Relationship_Characters_FirstCharacterId",
            column: x => x.FirstCharacterId,
            principalTable: "Characters",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        table.ForeignKey(
            name: "FK_Relationship_Characters_SecondCharacterId",
            column: x => x.SecondCharacterId,
            principalTable: "Characters",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        });

Я не понимаю, почему он также создал внешний ключ SecondCharacter, когда я определяю только один для FirstCharacter.Также.Я не уверен, что это правильный способ делать то, что я хочу, потому что я, очевидно, не очень понимаю, что происходит в вызовах .HasMany (). WithOne.Есть идеи?

...