Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/40: Рейтинг темы: голосов - 40, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 25.04.2020
Сообщений: 136
.NET 6

Как убрать nullable предупреждения в EF?

21.11.2021, 19:08. Показов 8613. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет! Подскажите как убрать nullable предупреждения в Entity Framework? В документации по EF есть статья про это, но у меня еще остались вопросы.

Рассмотрим пример из документации:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
 
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b.Posts)
            .HasForeignKey(p => p.BlogForeignKey);
    }
}
 
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
 
    public List<Post> Posts { get; set; }
}
 
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
 
    public int BlogForeignKey { get; set; }
    public Blog Blog { get; set; }
}
В примере из документации будут предупреждения:
Code
1
2
3
4
5
Warning CS8618  Non-nullable property 'Blogs' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
Warning CS8618  Non-nullable property 'Posts' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
Warning CS8618  Non-nullable property 'Url' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
Warning CS8618  Non-nullable property 'Posts' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
Warning CS8618  Non-nullable property 'Blog' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
Убрать предупреждения можно воспользовавшись советами из статьи в документации, в результате я получил такой код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs => Set<Blog>(); // изменение
    public DbSet<Post> Posts => Set<Post>(); // изменение
 
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b.Posts)
            .HasForeignKey(p => p.BlogForeignKey)
            .HasPrincipalKey(b => b.BlogId) // добавил
            .IsRequired(true); // добавил
    }
}
 
public class Blog
{
    public int BlogId { get; set; }
    public string? Url { get; set; }
 
    public List<Post> Posts { get; set; } = null!; // изменение
}
 
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
 
    public int BlogForeignKey { get; set; }
    public Blog Blog { get; set; } = null!; // изменение
}
Предупреждения ушли, в базе сгенерированы корректные таблицы. В данном примере Post обязательно должен ссылаться на Blog:
Code
1
2
3
`BlogForeignKey` int NOT NULL
...
CONSTRAINT `FK_Posts_Blogs_BlogForeignKey` FOREIGN KEY (`BlogForeignKey`) REFERENCES `blogs` (`BlogId`) ON DELETE CASCADE
Но что делать если я не хочу обязательной ссылки из Post в Blog (то есть Post может существовать сам по себе, не ссылаясь на конкретный Blog)? Я сделал так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs => Set<Blog>(); // изменение
    public DbSet<Post> Posts => Set<Post>(); // изменение
 
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b.Posts)
            .HasForeignKey(p => p.BlogForeignKey)
            .HasPrincipalKey(b => b.BlogId)
            .IsRequired(false); // изменение (FALSE)
    }
}
 
public class Blog
{
    public int BlogId { get; set; }
    public string? Url { get; set; }
 
    public List<Post>? Posts { get; set; } // изменение (добавлен ?)
}
 
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
 
    public int? BlogForeignKey { get; set; } // изменение (добавлен ?)
    public Blog? Blog { get; set; } // изменение (добавлен ?)
}
Были сгенерированы верны таблицы (поле BlogForeignKey таблицы Post может быть NULL):
Code
1
2
3
`BlogForeignKey` int DEFAULT NULL
...
CONSTRAINT `FK_Posts_Blogs_BlogForeignKey` FOREIGN KEY (`BlogForeignKey`) REFERENCES `blogs` (`BlogId`) ON DELETE RESTRICT
Но появилось несколько предупреждений "Warning CS8602 Dereference of a possibly null reference":


Как убрать данные предупреждения?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
21.11.2021, 19:08
Ответы с готовыми решениями:

Как убрать предупреждения при удалении листа в Excel
Использую Excel из VB. Необходимо в процессе работы программно удалить лист из Excel'я. Беда в том, что он выдаёт свои дурацкие...

Убрать предупреждения на break в операторе switch(...)
Никак не пойму, как можно перекроить этот код: //*************************************************************************** ...

Как организовать структуру, аналогично Nullable(of T)?
подскажите, как следует описать структуру, так чтобы экземпляр поддерживал синтаксис PeremStructure Is Nothing, аналогично структуре...

9
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18304 / 14228 / 5368
Регистрация: 17.03.2014
Сообщений: 28,901
Записей в блоге: 1
21.11.2021, 21:57
Лучший ответ Сообщение было отмечено tezaurismosis как решение

Решение

Цитата Сообщение от MrKamaBullet05 Посмотреть сообщение
Как убрать данные предупреждения?
Попробуйте добавить ! перед точкой
C#
1
2
3
4
5
6
7
8
9
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b!.Posts)
            .HasForeignKey(p => p.BlogForeignKey)
            .HasPrincipalKey(b => b!.BlogId)
            .IsRequired(false); // изменение (FALSE)
    }
3
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16141 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,126
Записей в блоге: 2
22.11.2021, 00:23
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Попробуйте добавить ! перед точкой
Не знал о таком.
1
Эксперт .NET
 Аватар для Usaga
14314 / 9399 / 1355
Регистрация: 21.01.2016
Сообщений: 35,438
22.11.2021, 07:38
MrKamaBullet05, да просто отключите проверку nullability для файла с кодом контекста. Я бы так и сделал. В данном случае это явно неуместные предупреждения.
2
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9674 / 4826 / 763
Регистрация: 17.04.2012
Сообщений: 9,664
Записей в блоге: 14
22.11.2021, 07:45
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Не знал о таком.
Как-то тоже упустил эту фичу, но сейчас нашёл: ! (null-forgiving) operator
2
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18304 / 14228 / 5368
Регистрация: 17.03.2014
Сообщений: 28,901
Записей в блоге: 1
22.11.2021, 08:26
MrKamaBullet05, обратите внимание на совет Usaga. Вероятно в данном случае действительно лучше добавить в начало файла
C#
1
#nullable disable
2
0 / 0 / 0
Регистрация: 25.04.2020
Сообщений: 136
22.11.2021, 23:57  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Вероятно в данном случае действительно лучше добавить в начало файла
А зачем? Лучше привыкну к новым нововведениям, когда nullable переменные желательно помечать символом "?", вроде бы хорошая задумка.

Цитата Сообщение от OwenGlendower Посмотреть сообщение
Попробуйте добавить ! перед точкой
Тоже не знал про такую возможность, предупреждения ушли

То есть, в нынешних реалиях пример из официальной документации должен выглядеть так?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs => Set<Blog>();
    public DbSet<Post> Posts => Set<Post>();
 
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b!.Posts)
            .HasForeignKey(p => p.BlogForeignKey)
            .HasPrincipalKey(b => b!.BlogId)
            .IsRequired(false);
    }
}
 
public class Blog
{
    public int BlogId { get; set; }
    public string? Url { get; set; }
 
    public List<Post>? Posts { get; set; }
}
 
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
 
    public int? BlogForeignKey { get; set; }
    public Blog? Blog { get; set; }
}
Все корректно?

Добавлено через 34 минуты
OwenGlendower, еще один вопрос возник! Давайте еще раз рассмотрим пример, когда Post должен обязательно иметь ссылку на Blog:
C#
1
2
3
4
5
6
public class Post
{
    ...
    public int BlogForeignKey { get; set; }
    public Blog Blog { get; set; } = null!;
}
Здесь свойство Blog не должно являться null ("null!"). Не смотря на то, что у Post обязательно будет Blog и свойство BlogForeignKey всегда будет иметь значение, свойство же Blog может быть null, если не будет загружено (context.Posts.Include(i => i.Blog))!! Так верно ли в таком случае присваивать свойству Blog значение "null!"?

Возможно, правильнее свойство Blog описать так:
public Blog? Blog { get; set; }
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16141 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,126
Записей в блоге: 2
23.11.2021, 00:25
Цитата Сообщение от MrKamaBullet05 Посмотреть сообщение
А зачем? Лучше привыкну к новым нововведениям, когда nullable переменные желательно помечать символом "?", вроде бы хорошая задумка.
Не всегда.
Если зависимые от nullable свойства - это некий блок (простой тип или их можно вынести в partial класс), то прозрачнее и понятнее будет задать #nullable enable всему файлу (ил к его части), чем при обращении к каждой переменной.

Цитата Сообщение от MrKamaBullet05 Посмотреть сообщение
Все корректно?
Что такое "корректно"?
Если с точки зрения "Будет компилироваться" - да.
Если "Упрощение кода и его читаемости" - вариант с #nullable более читаем.
1
0 / 0 / 0
Регистрация: 25.04.2020
Сообщений: 136
23.11.2021, 01:22  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Что такое "корректно"?
Если с точки зрения "Будет компилироваться" - да.
Компилироваться то будет, но насколько правильно это использовано. Я привел выше пример, в котором у нас Post должен обязательно ссылаться на Blog.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
// #1
public class Blog
{
    ...
    public List<Post> Posts { get; set; } = null!;
}
 
public class Post
{
    ...
    public int BlogForeignKey { get; set; }
    public Blog Blog { get; set; } = null!;
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
// #2
public class Blog
{
    ...
    public List<Post>? Posts { get; set; } // может быть null - необходимо использовать .Include(p => p.Posts)
}
 
public class Post
{
    ...
    public int BlogForeignKey { get; set; }
    public Blog? Blog { get; set; }; // может быть null - необходимо использовать .Include(p => p.Blog)
}
И вот какой вариант наиболее "корректен" с точки зрения использования нововведений (вопросиков и восклицательных знаков)?) Или нововведения плохо ложатся на использование с EF?
0
Эксперт .NET
 Аватар для Usaga
14314 / 9399 / 1355
Регистрация: 21.01.2016
Сообщений: 35,438
23.11.2021, 06:42
Цитата Сообщение от MrKamaBullet05 Посмотреть сообщение
А зачем? Лучше привыкну к новым нововведениям, когда nullable переменные желательно помечать символом "?", вроде бы хорошая задумка.
В данном случае предупреждения бессмысленны и явно врут. Лямбды что вы EF'у скармливаете исполняться не будут. И никаких Null Reference Exception там не будет. Но компилятор об этом не знает и ругается. Можете, конечно, в код конфигурации каждой сущности подсказки вписывать (? и !), но зачем лишнюю работу себе добавлять, если вы заранее знаете, что эти предупреждения неверные?

Цитата Сообщение от MrKamaBullet05 Посмотреть сообщение
Или нововведения плохо ложатся на использование с EF?
EF про них не знает. Ему до фонаря. В классах сущностей EF определяет опциональность навигационных свойств по типу ключа (int или int?), ему ? перед Blog не нужен для этого. Тут вы уже для себя аннотации раставляете. А внутри всяких WithMany и прочих методов эти аннотации не имеют смысла, ибо лямбды в эти методы передаваемые не исполняются. Это - обёртки в виде Expression Tree, которые EF анализирует в рантайме для генерации внутреннего представления модели данных и запросов.

Цитата Сообщение от MrKamaBullet05 Посмотреть сообщение
// может быть null - необходимо использовать .Include(p => p.Blog)
Кстати, фиговенький подход по работе с EF. Очень неоптимальный. Рекомендую почитать про проекции.
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.11.2021, 06:42
Помогаю со студенческими работами здесь

Как проверить, что тип T является типом Nullable<T1>?
Как проверить, что тип T является типом Nullable&lt;T1&gt;, где T1 неизвестный тип?

C БД забираются nullable integers, как с ними работать далее?
Здравствуйте. Столкнлся с nullable integers, которые забираются c БД. private void Send() { TestClass _testClass()

Как избавиться от предупреждения?
char Number; double Result = atof(Number); Result=(-1)*Result; _itoa(Result,Number,10); SetWindowText(Edit,Number); ...

Как избавиться от предупреждения
Есть такой код: #include &lt;iostream&gt; #include &lt;ctime&gt; #include &lt;thread&gt; #include &lt;windows.h&gt; using namespace std; using...

Как избавится от предупреждения?
Всем привет. Поставил арч, из пользователей только рут. Знаю так не принято, но в данном случае именно так надо. Из за того, что система...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru