Как я могу узнать, включены ли связанные данные при активной загрузке в Entity Framework? - PullRequest
0 голосов
/ 29 мая 2019

Я работаю над проектом, который использует шаблон репозитория. Мы используем Entity Framework для извлечения данных из базы данных. Для загрузки связанных данных мы используем Eager loading, что означает, что мы должны явно включать связанные данные.

Скажем, что мы хотим иметь все блоги и связанные с ними посты, которые мы должны написать: _dbContext.Blogs.include(b => b.Posts).

Недостатки этого метода в том, что вы можете видеть, какие связанные данные загружены в класс репозитория.

Я попытался показать пример ниже. Здесь проблема возникает в классе BlogViewModel.cs, потому что вы пытаетесь получить доступ к blogs.Posts, но сообщения не включены в исходный запрос. Поэтому, если вы пытаетесь получить связанные данные, нужно проверить источник запроса и посмотреть, включен ли он.

Repostiory.cs

  public IEnumerable<BlogDbModel> GetBlogs()
    {

        return _dbContext.Blogs.ToList();
    }

Service.cs

public IEnumerable<BlogViewModel> GetBlogs() {
  return _repository.Select(x => new BlogViewModel(x));
 }

BlogViewModel.cs

public class BlogViewModel {
  public BlogViewModel(BlogDbModel blogDbModel) {
    Name = blogDbModel.Name;
    Posts = blogDbModel.Posts;
}

  public string Name { get; set;}

  public IEnumberable<Posts> Posts {get; set;}

}

У кого-нибудь есть умное решение для этого? Можно ли выдать ошибку компиляции, если вы пытаетесь получить доступ к данным, которые не включены?

Два варианта, о которых я подумал:

  1. Вместо этого используйте Lazy loading.
  2. Всегда возвращать IQueryable из хранилища

спасибо

1 Ответ

1 голос
/ 29 мая 2019

Нет, у вас нет возможности выдать ошибку компиляции в этом контексте.Данные в любом случае загружаются во время выполнения.

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

public BlogViewModel(BlogDbModel blogDbModel) 
{
  Name = blogDbModel.Name;
  Posts = blogDbModel.Posts;
 }

Если вы включите lazyload и сделаете это сообщение будет получено с использованием функции lazyload.Что если сообщение содержит ссылку на User или любой другой объект, то оно тоже будет загружено.Когда вам все нужно на первом месте, не рекомендуется использовать lazyload, потому что это приведет к дополнительному обращению к базе данных.

IQueryable из репозитория

Я бы сказал, IQueryable дляviewmodel - это дырявая абстракция.В идеале ваш уровень данных должен выполнять это.Предоставление IQuerable<BlogDbModel> для Viewmodel похоже на то, как разработчик может выбрать 1Blogs => Post => User => Accounts1, что-нибудь связанное с этим.

ИМХО Я бы написал методы уровня данных, необходимые для представления.

LazyloadingEnabled = false;

public IEnumerable<BlogDbModel> GetBlogs()
{

    return _dbContext.Blogs.ToList();
}

public IEnumerable<BlogDbModel> GetBlogsAndPosts()
{

  return _dbContext.Blogs.Include("Posts").ToList();
}

//This will fetch only what is needed (You can customize to get columns what is needed)
public IEnumerable<NewCustomDTO> GetBlogsAndPostCount()
{

   return _dbContext.Blogs.Select(x=> NewCustomDTO
   {
       BlogName = x.BlogName,
       Count = x.Posts.Count(),
   });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...