Как сопоставить собственность в частном поле - PullRequest
1 голос
/ 07 ноября 2019

У меня есть объект значения, что означает, что его свойства имеют геттеры, но не сеттерыТогда у меня есть сущность с публичным получателем и приватным полем. Примерно так:

public class Settings {
  private string _instance;
  private string _domain;

  public Settings(string instance, string domain) {
    _instance = instance;
    _domain = domain;
  }
  private Settings() {
    _instance = default!;
    _domain = default!;
  }

  public string Instance => _instance;
  public string Domain => _domain;
}

public class Tenant {
  private Guid _id;
  private string _name;
  private Settings _settings;

  public Tenant(string name) {
    _id = Guid.Empty;
    _name = name;
    _settings = new Settings("etc", "etc");
  }
  private Tenant() {
    _id = default;
    _name = default!;
    _settings = default!;
  }

  public Guid Id => _id;
  public string Name => _name;
  public Settings => _settings;

  protected void OnSettingsChanged() { 
    // do stuff like adding domain events and sending notifications 
  }
  public void ChangeSetting(Settings newSettings) {
    // do some model validation
    _settings = newSettings;
    OnSettingsChanged();
  }
}

Я использую C # 8, .NET Core 3 и Entity Frmework Core 3. Теперь в моей реализации IEntityTypeConfiguration<Tenant> для настройки скажем Name у меня нет проблем, так какЯ могу использовать HasField и передать имя частной собственности. Но это не работает для настроек. Там я использую OwnsOne, но нет доступного свойства HasField.

builder.Property(x => x.Name)
  .HasField("_name")
  .HasMaxLength(100);
builder.OwnsOne(x.Settings, y => {
  y.Property(z => z.Instance)
   .HasField("_instance")
   .IsRequired(true);
  y.Property(z => z.Domain)
   .HasField("_domain")
   .IsRequired(true);
  //y.HasField() ??
});

Однако я не могу найти способ сообщить EF, что свойство Settings должно быть сопоставлено с закрытой переменной _settings. Я попытался добавить вызов к Property перед вызовом на OwnsOne:

...
builder.Property(x => x.Settings)
  .HasField("_settings");
builder.OwnsOne(x.Settings, y => {
  y.Property(z => z.Instance)
   .HasField("_instance")
   .IsRequired(true);
  y.Property(z => z.Domain)
   .HasField("_domain")
   .IsRequired(true);
});

Но затем, когда я добавляю миграцию, я получаю сообщение об ошибке: свойство или навигацию «Настройки» нельзя добавить втип сущности «Арендатор», потому что свойство или навигация с тем же именем уже существует в типе сущности «Арендатор», что, как я полагаю, происходит из-за того, что я дважды настраиваю свойство «Настройки».

Итак, как мне этого добиться? что эквивалентно HasField при использовании OwnsOne? Заранее спасибо.

1 Ответ

1 голос
/ 07 ноября 2019

Вам не нужны все эти HasField вызовы, потому что в EF Core 3.0 поля поддержки используются по умолчанию , а также ваши поля поддержки соответствуют одному из соглашений именования полей поддержки свойств EF Core . , поэтому EF Core автоматически обнаружит и использует их (вам по-прежнему нужны Property вызовы, хотя, поскольку соглашения о получении только свойств не обнаружены в соответствии с соглашением).

Но допустим, вам нужно указать поле поддержкисобственность в вопросе. Property метод не может быть использован, потому что по терминологии EF Core это не свойства, а навигация . Для конструкторов свойств не существует плавного API, аналогичного HasField, поэтому вы должны напрямую использовать службы изменяемых метаданных:

builder.OwnsOne(x => x.Settings, y =>
{
    // ...
    y.Metadata.PrincipalToDependent.SetField("_settings");
});

Это похоже на свойства навигации по отношениям. Свойство Metadata соответствующего компоновщика возвращает объект IMutableForegnKey. Свойства PrincipalToDependent и DependentToPrincipal возвращают IMutableNavigation объекты, которые можно использовать для настройки соответствующего свойства навигации.

...