Свойство навигации EF core равно нулю

#c# #.net #sql-server #entity-framework #entity-framework-core

Вопрос:

Я пытаюсь создать первые схемы кода с 2 сущностями:

  • запрос
  • сертификат

запрос может иметь (необязательно) сертификат, но у сертификата всегда есть запрос (ноль или один к одному)

Я определил сущность следующим образом :

 public class Request
{
    public virtual Certificate Certificate { get; set; }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public long RequestID { get; set; }

    public string fieldA { get; set; }
}

public class Certificate
{
    public virtual Request Request { get; set; }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public long RequestID { get; set; }

    public string fieldB { get; set; }
}
 

И взаимосвязь четко определена в построителе моделей :

 protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Request>().ToTable("Requests");
    modelBuilder.Entity<Certificate>().ToTable("Certificates");

    modelBuilder.Entity<Request>()
        .HasOne<Certificate>(item => item.Certificate)
        .WithOne(item => item.Request)
        .HasForeignKey<Certificate>(item => item.RequestID);
}
 

Модель построена правильно, и я могу сохранять сущности, но когда я запрашиваю запрос, у которого есть сертификат, свойство навигации остается нулевым :

 Request req = await db.Requests.FirstOrDefaultAsync(item => item.RequestID == 1);
// req.Certificate is null
 

Что я упускаю ?

Использование EntityFrameworkCore V5.0.6 и .net 5

Комментарии:

1. Загрузка Связанных Данных

Ответ №1:

Вам необходимо вручную включить свойства навигации. Попробуй

 Request req = await db.Requests.Include(r => r.Certificate).SingleOrDefaultAsync(item => item.RequestID == 1);
 

Также вы можете избавиться от виртуального, если не хотите включить ужасную ленивую загрузку (по умолчанию отключена).

Комментарии:

1. Если прокси-серверы LazyLoad не включены, вам может потребоваться удалить virtual ключевое слово, иначе ядро EF будет загружено и даже .Include не будет загружать связанную сущность. (На основе других сообщений о странностях /w .Include() «не работает» в ядре EF.) Лично я использую LazyLoad как безотказный, но настоятельно рекомендую ознакомиться с проекцией ( Select / ProjectTo ), чтобы создавать более эффективные запросы, не сталкиваясь с проблемами ленивой/нетерпеливой загрузки.

2. В конце концов я выяснил, где в EF6 ленивая загрузка была включена по умолчанию, здесь вы должны включить ее (с optionsBuilder.UseLazyLoadingProxies() ) и добавить Microsoft.EntityFrameworkCore.Proxies пакет

3. ДА. Но не делай этого.

Ответ №2:

В EF core автоматические прокси-серверы (отложенная загрузка) по умолчанию отключены.

Чтобы включить их, установите пакет Microsoft.EntityFrameworkCore.Прокси

 install-package Microsoft.EntityFrameworkCore.Proxies
 

и включите их в конструкторе опций

 optionsBuilder.UseLazyLoadingProxies();