Я работаю над проектом, использующим шаблон репозитория. Мы используем Entity Framework для извлечения данных из базы данных. Для загрузки связанных данных мы используем активную загрузку, что означает, что мы должны явно указать данные, связанные с включать.
Скажем, мы хотим, чтобы все блоги и связанные с ними сообщения мы должны были написать:
_dbContext.Blogs.Include(b => b.Posts)
Недостатком этого является то, что вы можете видеть только те связанные данные, которые загружены в класс репозитория.
Я попытался показать пример ниже. Здесь проблема возникает в классе BlogViewModel.cs
, потому что вы пытаетесь получить доступ к blogs.Posts
, но сообщения не включены в исходный запрос. Поэтому, если вы пытаетесь получить связанные данные, нужно будет проверить источник запроса и посмотреть, включен ли он.
Repository.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 IEnumerable<Posts> Posts { get; set; }
}
У кого-нибудь есть умное решение для этого? Возможно ли дать ошибку компиляции, если вы пытаетесь получить доступ к данным, которые не включены?
Два варианта, о которых я подумал:
IQueryable
из репозиторияСпасибо
[ { Название: 'Блог Джонни', Сообщения: [ { title: 'Жизнь в дороге}' text: 'Всем привет... }, { title: 'Где я}' text: 'Так здорово... ] }], { Имя: 'Chrisitinas place', Сообщения: [ ....... ] } ]
Это то, что вы имели в виду @Innominatum? :С
Да, глядя на ваш фрагмент, список сообщений загружен, но пуст, есть ли связь между данными BlogViewModel и сообщениями?
Я думаю, что мой вопрос, возможно, был истолкован неправильно. @Элдо понял. спасибо за попытку :)
Нет, у вас нет возможности указать ошибку компиляции в этом контексте. Данные в любом случае загружаются во время выполнения.
Ленивая загрузка
Предполагая, что вы отображаете блоги, сообщения, комментарии, поэтому вам нужно загружать все при загрузке страницы.
Когда вы включаете lazyload
и свойства карты, которые не были включены в запрос уровня данных, он будет загружать связанные объекты.
public BlogViewModel(BlogDbModel blogDbModel)
{
Name = blogDbModel.Name;
Posts = blogDbModel.Posts;
}
Если вы включите отложенную загрузку и сделаете это, этот пост будет загружен с использованием функции отложенной загрузки. Что, если сообщение содержит ссылку на User
или любой другой объект, он также загрузит их.
Когда вам нужно все в первую очередь, не рекомендуется использовать отложенную загрузку, потому что это потребует дополнительного обращения к базе данных.
IQueryable из репозитория
Я бы сказал, что IQueryable для модели представления — это дырявая абстракция. В идеале ваш уровень данных должен выполнять это. Предоставление 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(),
});
}
Хорошо. это хороший момент. Проблема с этим подходом заключается в том, что Блоги имеет десять связанных сущностей, у которых снова есть несколько сущностей. Поэтому в репозитории пришлось бы делать много методов. GetBlogsAndPosts, GetBlogsAndPostsAndAuthors и т. д. Я предполагаю, что мой подход будет простой конечной точкой GetBlogs и конечной точкой GetBlogsAndRelatedData.
Я думаю, GetBlogs всегда нужны авторы, комментарии и лайки. Простые методы, такие как GetBlogs, которые возвращают только блоги, необходимы при его использовании. Я бы сказал, напишите методы, что необходимо. В разработке нет серебряной пули, но есть компромиссы, которые лучше всего подходят для вашей ситуации.
Случай с блогами и постами был просто для примера :). На самом деле это нечто гораздо более скучное :). Спасибо еще раз
некоторые справочные мысли о ленивой загрузке ardalis.com/avoid-lazy-loading-entities-in-asp-net-приложения
Не могли бы вы поделиться фрагментом вывода, когда вы включаете сообщения в запрос?