EF Core 3: настройка поля поддержки свойства навигации

Рассмотрим следующий класс. Он пытается защитить доступ к _assignedTrays.

На самом деле, это работает отлично, поскольку EF автоматически связывает поле поддержки _assignedTrays со свойством AssignedTrays - по соглашению (msdn)

    public class Rack
    {
        private List<Tray> _assignedTrays = new List<Tray>();

        private Rack()
        {
        }

        public Rack(string rackId)
        {
            this.Id = rackId;
        }

        public string Id { get; private set; }

        public IReadOnlyList<Tray> AssignedTrays => this._assignedTrays.AsReadOnly();

        public void Assign(params Tray[] trays)
        {
            this._assignedTrays.AddRange(trays);
        }
    }

Проблема в том, что наши стили кодирования запрещают использование подчеркиваний в именах переменных ;-)

Согласно другим примерам кода (здесь) должна быть возможность просто переименовать _assignedTrays в assignedTrays и просто явно сообщить EF об этом изменении в OnModelCreating:

    modelBuilder.Entity<Rack>(e =>
    {
        e.Property(t => t.AssignedTrays).HasField("assignedTrays");
    });

Но это дает мне следующее исключение:

System.InvalidOperationException: The property 'Rack.AssignedTrays' is of type 'IReadOnlyList<Tray>' which 
is not supported by current database provider. Either change the property CLR type or ignore the property
using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

Что мне здесь не хватает? Разве это не должно работать?


person thomai    schedule 10.03.2020    source источник
comment
Я не думаю, что ты действительно можешь что-то сделать. Обходным путем было бы переименовать поле поддержки, например internalAssignedTrays, и добавить комментарий о том, почему вы не можете назвать это как-то иначе, чтобы оно прошло проверку кода.   -  person DavidG    schedule 10.03.2020
comment
Меня можно сопоставить по-другому (метод Property не для свойств навигации), но в этом нет необходимости, поскольку соглашение EF Core поддерживает ваш стиль именования.   -  person Ivan Stoev    schedule 10.03.2020
comment
@IvanStoev Но соглашение не допускает этого соглашения без подчеркивания.   -  person DavidG    schedule 10.03.2020
comment
@DavidG К сожалению, документация кажется неполной, <camel-cased property name> (соглашение об именах полей поддержки C # по умолчанию) также поддерживается - вероятно, с наивысшим приоритетом.   -  person Ivan Stoev    schedule 10.03.2020
comment
@IvanStoev: Вы правы. Мне было интересно, почему интеграционные тесты стали зелеными, когда не использовалась конфигурация HasField, но я возложил вину за это на «неполные тесты» ...   -  person thomai    schedule 10.03.2020


Ответы (1)


В документации не отражены действительные правила, потому что <camel-cased property name> ("стандартное" соглашение об именах полей поддержки C #) определенно поддерживается и, вероятно, даже с наивысшим приоритетом.

Но допустим, ваше соглашение об именах не поддерживается. Вы по-прежнему можете сопоставить резервное поле, но вы не можете сделать это с Property fluent API, потому что по терминологии EF Core свойства навигации - это не «свойства», а «навигация». Это применимо ко всем API-интерфейсам для свободного использования, отслеживания изменений и т. Д.

Для настройки навигации вам необходимо получить доступ к построителю отношений. Затем вы можете использовать свойства PrincipalToDependent и DependentToPrrncipal связанных метаданных для доступа / настройки двух концов взаимосвязи.

Или используйте напрямую API-интерфейсы метаданных (в настоящее время для этого нет специального свободного API).

Например:

modelBuilder.Entity<Rack>()
    .FindNavigation(nameof(Rack.AssignedTrays))
    .SetField("assignedTrays");
person Ivan Stoev    schedule 10.03.2020