Почему связанные объекты не загружаются в .Include ()? - PullRequest
0 голосов
/ 01 мая 2019

Кто-нибудь может мне сказать, почему связанные Article сущности не загружаются на .Include(a => a.Article)? Они всегда NULL, хотя ArticleId действительно имеет значение. Соотношение между FrontPageItem и Article составляет 1-0..1. Article может существовать без какого-либо подключения к FrontPageItem, но FrontPageItem должен иметь один Article.

В довольно уродливом обходном пути я прибегнул к foreach, просматривая все возвращенные элементы в списке и добавляя Article вручную, как вы можете видеть в моем методе index ниже.

public async Task<IActionResult> Index()
{
    List<FrontPageItem> items = await db.FrontPageItems
        .Include(a => a.Article)
            .ThenInclude(c => c.CreatedBy)
                .ThenInclude(m => m.Member)
        .Include(a => a.Article)
            .ThenInclude(e => e.EditedBy)
                .ThenInclude(m => m.Member)
        .Include(a => a.Article)
            .ThenInclude(e => e.PublishReadyBy)
                .ThenInclude(m => m.Member)
        .Include(p => p.WebPage)
        .OrderByDescending(o => o.DatePublished)
        .ToListAsync();
    // I don't want to foreach, but without it, Article is always NULL for all items.
    foreach (FrontPageItem item in items)
    {
        item.Article = await db.Articles
            .Where(a => a.Id == item.ArticleId).FirstOrDefaultAsync();
    }
    List<FrontPageItemViewModel> vm = 
        auto.Map<List<FrontPageItemViewModel>>(items);
    return View(vm);
}

Это модели:

public class FrontPageItem
{
    public int Id { get; set; }
    // ... some more properties
    public int? ArticleId { get; set; }
    public Article Article { get; set; }

    public AdminUser CreatedBy { get; set; }
    public AdminUser EditedBy { get; set; }
    public AdminUser PublishedBy { get; set; }

}

public class Article
{
    public int Id { get; set; }
    // ... some more properties
    public int? FrontPageItemId { get; set; }
    public FrontPageItem FrontPageItem { get; set; }

    public AdminUser CreatedBy { get; set; }
    public AdminUser EditedBy { get; set; }
    public AdminUser PublishReadyBy { get; set; }
}

public class AdminUser
{
    public int Id { get; set; }
    // ... some more properties
    public int MemberId { get; set; }
    public Member Member { get; set; }
}

public class Member
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    // ... some more properties
    public AdminUser AdminUser { get; set; }
}

Это модель-строитель:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Article>()
        .HasOne(p => p.FrontPageItem)
        .WithOne(i => i.Article)
        .HasForeignKey<Article>(b => b.FrontPageItemId);
}

1 Ответ

0 голосов
/ 02 мая 2019

Сначала вы должны понять, что такое Eager Loading, Lazy Loading, явная загрузка

Стремительная загрузка

Eager Loading поможет вам загрузить все необходимые объекты одновременно; то есть все ваши дочерние объекты будут загружены за один вызов базы данных. Это может быть достигнуто с помощью метода Include, который возвращает связанные объекты как часть запроса, и большой объем данных загружается сразу.

Ленивая загрузка

Это поведение по умолчанию Entity Framework, где ребенок объект загружается только при первом обращении к нему. Это просто задерживает загрузку соответствующих данных, пока вы не попросите об этом.

явная загрузка

В Entity Framework есть возможность отключить отложенную загрузку. Отключив Ленивую загрузку, вы все равно можете загрузить явный вызов метода Load для связанных объектов. Есть два способа использования метода Load Reference (для загрузки одиночной навигации свойство) и Collection (для загрузки коллекций)

Таким образом, чтобы загрузить реляционную сущность, вы можете использовать пакет Microsoft.EntityFrameworkCore.Proxies, чтобы включить отложенную загрузку. Поэтому при запросе к базе данных EF будет возвращать реляционную базу данных об их отношениях

Мой пример кода выглядит так

services.AddDbContextPool<ApplicationDbContext>(options =>
  options.UseLazyLoadingProxies().UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
        b => b.MigrationsAssembly("AwesomeCMSCore")).UseOpenIddict());

Пожалуйста, дайте мне знать, если у вас возникли проблемы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...