Есть сущность
public class Message : BaseEntity
{
// some other fields
public int[] AttachmentsIds { get; set; }
public Attachment[] Attachments { get; set; }
}
Планировалось, что первое поле будет браться из БД, потом по списку Id
будет запрошены данные из другой таблицы и заполнено второе поле.
Для этого я думал написать репозитории для Message
и Attachments
, а затем сервис, который используя оба эти репозитория бы возвращал уже заполненную сущность Message
или коллекцию сущностей.
Примерно так я представлял себе метод для получения всех сообщений с заполненными вложениями
public interface ISpecification<T>
{
Expression<Func<T, bool>> Criteria { get; }
}
//...
IMessageRepository messageRep = ... ;
IAttachmentRepository attachmentRep = ... ;
//...
public IEnumerable<Message> GetMessagesWithAttachments(ISpecification<Message> spec)
{
IEnumerable<Message> messages = messageRep.All.Where(spec.Criteria).ToList(); //All - IQueryble
IEnumerable<int> attachmentsIds = messages.Select(m => m.AttachmentsIds).SelectMany(ids => ids).Distinct().ToList();
IEnumerable<Attachments> attachments = attachmentRep.All.Where(id => attachmentsIds.Contains(id));
foreach (var message in messages)
{
message.Attachments = attachmentsIds.Where(id => message.AttachmentsIds.Contains(id)).ToList();
}
return messages;
}
Запрашиваем все посты по фильтру, получаем список встреченных вложений, получаем его, а затем тасуем вложения по сообщениям.
Но если я хочу использовать пагинацию (или просто Skip и Take) или если мне необходимо сначала отсортировать, а потом сделать выборку, то непонятно как это сделать.
Решение в лоб, которое приходит в голову:
// модифицировать метод
public IEnumerable<Message> GetMessagesWithAttachments(IQueryble<Message> messages)
{
IEnumerable<int> attachmentsIds = messages.Select(m => m.AttachmentsIds).SelectMany(ids => ids).Distinct().ToList();
IEnumerable<Attachments> attachments = attachmentRep.All.Where(id => attachmentsIds.Contains(id));
foreach (var message in messages)
{
message.Attachments = attachmentsIds.Where(id => message.AttachmentsIds.Contains(id)).ToList();
}
return messages;
}
//...
//и вызывать так:
IEnumerable<Message> messages = messageService.GetMessagesWithAttachments(
messageService.All
.OrderBy(...)
.Where(...)
.Skip(...)
.Take(...)
);
Но решение не выглядит красивым и/или правильным =/
(Если есть советы по поводу самой архитектуры, то вот тут вопрос, на который ещё не ответили: Строки одной таблицы как столбец в другой )
Виртуальный выделенный сервер (VDS) становится отличным выбором
Есть ли какой-либо мануал более вменяемый чем официальная документация?