Работа со ссылочными типами допускающими значение NULL EF Core Microsoft docs

Работа с ссылочными типами, допускающими значение NULL.

В C # 8 появилась новая функция, называемая ссылочными типами, допускающими значение NULL (NRT), позволяющая аннотировать ссылочные типы, указывая, допустимо ли для них содержать значение NULL. Если вы новичок в этой функции, рекомендуется ознакомиться с ней, прочитав документацию по C #..

На этой странице представлена ​​поддержка EF Core ссылочных типов, допускающих значение NULL, и описаны передовые методы работы с ними..

Обязательные и необязательные свойства.

Основная документация по обязательным и дополнительным свойствам и их взаимодействию со ссылочными типами, допускающими значение NULL, находится на странице обязательных и дополнительных свойств. Рекомендуется начать с чтения этой страницы..

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

Свойства и инициализация, не допускающие значения NULL.

Когда включены ссылочные типы, допускающие значение NULL, компилятор C # выдает предупреждения для любого неинициализированного свойства, не допускающего значения NULL, поскольку они будут содержать значение NULL. В результате нельзя использовать следующий распространенный способ записи типов сущностей:

Привязка конструктора — полезный метод, гарантирующий, что ваши свойства, не допускающие значения NULL, инициализированы:

К сожалению, в некоторых сценариях привязка конструктора невозможна; например, свойства навигации не могут быть инициализированы таким образом.

Обязательные свойства навигации представляют дополнительную сложность: хотя зависимый объект всегда будет существовать для данного принципала, он может или не может быть загружен конкретным запросом, в зависимости от потребностей в этой точке программы (см. Различные шаблоны для загрузки данных) . В то же время нежелательно делать эти свойства обнуляемыми, так как это заставит весь доступ к ним проверять на null, даже если они требуются..

Один из способов справиться с этими сценариями — иметь свойство, не допускающее значения NULL, с поддерживающим полем, допускающим значение NULL:

Поскольку свойство навигации не допускает значения NULL, настроена необходимая навигация; и пока навигация правильно загружена, зависимый будет доступен через свойство. Если, однако, доступ к свойству осуществляется без предварительной загрузки связанной сущности, возникает исключение InvalidOperationException, поскольку контракт API использовался неправильно. Обратите внимание, что EF должен быть настроен так, чтобы всегда получать доступ к резервному полю, а не к свойству, поскольку он полагается на возможность чтения значения, даже если оно не задано; обратитесь к документации по полям поддержки, чтобы узнать, как это сделать, и подумайте об указании PropertyAccessMode.Field, чтобы убедиться, что конфигурация верна..

В качестве более краткой альтернативы можно просто инициализировать свойство равным нулю с помощью оператора, допускающего нуль (!):

Фактическое нулевое значение никогда не будет наблюдаться, кроме как в результате ошибки программирования, например. доступ к свойству навигации без предварительной загрузки связанной сущности.

Навигации по коллекциям, которые содержат ссылки на несколько связанных сущностей, всегда не должны допускать значения NULL. Пустая коллекция означает, что связанных сущностей не существует, но сам список никогда не должен быть нулевым..

DbContext и DbSet.

Обычная практика наличия неинициализированных свойств DbSet для типов контекста также проблематична, поскольку теперь компилятор будет выдавать для них предупреждения. Это можно исправить следующим образом:

Другая стратегия — использовать автоматические свойства, не допускающие значения NULL, но инициализировать их значением NULL, используя оператор, допускающий значение NULL (!), Чтобы отключить предупреждение компилятора. Базовый конструктор DbContext гарантирует, что все свойства DbSet будут инициализированы, и на них никогда не будет наблюдаться null..

Навигация и включение отношений, допускающих значение NULL.

При работе с необязательными отношениями можно встретить предупреждения компилятора, когда фактическое исключение нулевой ссылки было бы невозможно. При переводе и выполнении ваших запросов LINQ EF Core гарантирует, что, если необязательный связанный объект не существует, любая навигация по нему будет просто проигнорирована, а не выбрана. Однако компилятор не знает об этой гарантии EF Core и выдает предупреждения, как если бы запрос LINQ был выполнен в памяти с LINQ to Objects. В результате необходимо использовать оператор, допускающий значение NULL (!), Чтобы сообщить компилятору, что фактическое значение NULL невозможно:

Аналогичная проблема возникает при включении нескольких уровней отношений в дополнительные элементы навигации:

Если вы обнаружите, что делаете это часто, а рассматриваемые типы сущностей преимущественно (или исключительно) используются в запросах EF Core, подумайте о том, чтобы сделать свойства навигации непустыми и настроить их как необязательные с помощью Fluent API или аннотаций к данным. Это удалит все предупреждения компилятора, оставив связь необязательной; однако, если ваши объекты обрабатываются за пределами EF Core, вы можете наблюдать нулевые значения, хотя свойства аннотируются как не допускающие значения NULL..

Похожие статьи