Как настроить внешний ключ в свойстве EF-объекта? - PullRequest
0 голосов
/ 02 октября 2019

EF Core 3.0

У меня есть следующие (упрощенные) объекты в моем домене:

class ApplicationUser {
    public int Id { get; set; }
    public string UserName { get; set; }
    // other properties
}

[Owned]
class Stamp {
    public string Username { get; set; }
    public ApplicationUser User { get; set; }
    DateTime DateTime { get; set; }
}

class Activity {
    public Stamp Created { get; set; }
    public Stamp Modified { get; set; }
    // other properties
}

Это не особенно актуально, но стоит упомянуть, что ApplicationUser.UserName - это не первичный, уникальный ключ. (ApplicationUser на самом деле наследуется от ASP.NET IdentityUser.)

Я хочу убедиться, что Stamp.Username является внешним ключом, ссылающимся на ApplicationUser.UserName.

Если бы Stamp была обычной, не принадлежащей сущностью, это установило бы эту связь:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // Stamp.Username => ApplicationUser.UserName
    modelBuilder.Entity<Stamp>(e => {
        e.HasOne(s => s.User)
        .WithOne()
        .HasForeignKey<Stamp>(s => s.Username)
        .HasPrincipalKey<ApplicationUser>(u => u.UserName);
    });
    ...
}

Когда я пытаюсь создать миграцию (dotnet ef migrations add) Я получаю InvalidOperationException с надписью «Тип« Штамп »не может быть сконфигурирован как не принадлежащий, потому что принадлежащий тип сущности с таким именем уже существует».

Как добиться того, что я пытаюсь сделать, используя Fluent API или другим способом?

1 Ответ

0 голосов
/ 02 октября 2019

Это одно из возможных решений, вероятно, не самое элегантное. Он основан на этом ответе , упомянутом ChW в комментариях.

modelBuilder.Entity<Activity>(e => {
    e.OwnsOne(a => a.Created)
    .HasOne<ApplicationUser>()
    .WithOne()
    .HasForeignKey<Stamp>(s => s.Username)
    .HasPrincipalKey<ApplicationUser>(u => u.UserName);
});

Это устанавливает требуемый внешний ключ в конкретном Stamp вхождении (Created) для конкретноголицо-владелец (Activity).

Подобный блок кода, очевидно, нужно будет повторять для каждого другого Stamp вхождения (в данном примере Modified) и для каждого другого объекта-владельца (Activity может быть не единственным).

Кстати, я также удалил свойство навигации Stamp.User, потому что EF использовал его для автоматического создания другого внешнего ключа, который (нежелательно) указывал на свойство ApplicationUser.Id.

...