Если я не ошибаюсь, backing fields используются для того, чтобы скрыть внутреннюю структуру и бизнес-логику от посторонних глаз, но здесь EF может отобразить private field.
Как EF может знать, что режим доступа должен быть полевым, если он не может знать, что находится за публичным свойством?
Вы правы, что приватные поля должны быть приватными. Однако это не означает, что никто не может получить доступ к этой информации, это просто означает, что (в общем случае) они не должны этого делать.
Отражение позволяет обойти модификаторы доступа, чтобы получить доступ к тому, к чему вы обычно не можете. Сериализаторы и десериализаторы, такие как Newtonsoft.JSON и EF Core, используют отражение, чтобы (де)сериализовать объекты, которые вы хотите (де)сериализовать.
Именно так EF Core может "увидеть" ваши приватные поля.
Как человек, который реализует это отображение, может знать, что у Order есть поле _buyerId? Это приватное поле.
.Property<int?>("_buyerId")
.UsePropertyAccessMode(PropertyAccessMode.Field)
Обратите внимание, что в коде используется строковое представление имени поля. Если бы вы использовали реальную ссылку, например x => x._buyerId
, компилятор бы отказался, потому что это приватное поле и к нему нельзя обращаться в синтаксисе.
Отражение находит способ обойти компилятор, потому что отражение работает во время выполнения. Это объяснение очень упрощенное, но во время выполнения reflection заглянет во внутреннее устройство объекта, чтобы выяснить, какие поля у него есть, и затем сможет получить доступ к содержащимся в них данным.
Что .Property<int?>("_buyerId").UsePropertyAccessMode(PropertyAccessMode.Field)
- это дать указание EF Core искать поле с именем _buyerId
, используя отражение во время выполнения. Компилятор не выдает ошибку, потому что это не происходит во время компиляции.
Короче говоря, EF Core использует определенный способ построения/развертывания своих сущностей, который полностью игнорирует модификаторы доступа, установленные вами для ваших полей и свойств.
Почему EF Core делает это? В частности, для того, чтобы EF Core мог выполнять свою работу, не заставляя вас делать ваши поля публичными. В противном случае вы были бы вынуждены сделать все поля общедоступными, чтобы EF Core мог получить к ним доступ, а это будет стоить вам того, что вы больше не сможете рассчитывать на конфиденциальность ваших полей.
Учитывая это, я считаю, что вам не следует отображать ваши доменные объекты прямо в EF, и вместо этого вы должны использовать другую сущность, на которую вы отображаете ваш доменной объект; но это не главный вопрос, который был задан.