Контекст: У меня есть таблица Items
, каждая из которых имеет динамическое множество дескрипторов, называемых Tags
.Каждый Tag
принадлежит TagType
, который определяет, какую информацию представляет Tag
(размер, цвет, форма и т. Д.).Каждый Item
может иметь максимум один Tag
на TagType
.
Цель: Я хотел бы отобразить таблицу всех моих Items
и иметьстолбец в каждой строке с вложенной таблицей <th>TagTypes</th>
и <td>Tags</td>
с пустыми ячейками, если Item
не имеет Tag
для этого TagType
.
Проблема: Запрос Linq занимает не менее 30 секунд всего с 5000 Items
.Я ожидаю получить 100k + Items
.Мне нужно найти способ более эффективного заполнения этой информации.
Модели : (без учета несвязанных свойств)
public class Item : BaseEntity
{
public virtual ICollection<ItemTag> ItemTags { get; set; }
}
public class ItemTag
{
public Guid ItemId { get; set; }
public virtual Item Item {get; set;}
public Guid TagId { get; set; }
public virtual Tag Tag { get; set; }
}
public class Tag : BaseEntity
{
[Required]
[MaxLength(100)]
public string Value { get; set; }
[Required]
public Guid TagTypeId { get; set; }
public virtual TagType TagType {get;set;}
public virtual ICollection<ItemTag> ItemTags { get; set; }
}
public class TagType : BaseEntity
{
[Required]
[MaxLength(50)]
public string Name { get; set; }
public int Position { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
Затем у меня есть модель дисплея DisplayItem
, которую я конвертирую в Json и возвращаю.
public class DisplayItem
{
public Guid Id { get; set; }
public List<DisplayTag> ItemTags { get; set; }
public DisplayItem(Item itm, IList<TagType> tts)
{
Id = itm.Id;
ItemTags = GetDisplayTags(itm.ItemTags
.Select(it => it.Tag).ToList(), tts);
}
public List<DisplayTag> GetDisplayTags(IList<Tag> tags, IList<TagType> tts)
{
return tts.Select(tt => new DisplayTag(tt.Name,
tags.FirstOrDefault(t => t.TagTypeId == tt.Id)?.Value ?? " ")).ToList();
}
}
Запрос:
public async Task<JsonResult> OnGetItemsAsync()
{
TagTypes = await _context.TagType.OrderBy(tt => tt.Position).AsNoTracking().ToListAsync();
return new JsonResult(await _context.Items
.Include(itm => itm.ItemTags)
.ThenInclude(it => it.Tag)
.ThenInclude(t => t.TagType)
.AsNoTracking()
.Select(itm => new DisplayItem(itm, TagTypes))
.ToListAsync());
}
Самая медленная часть, кажется, GetDisplayTags(itm.ItemTags.Select(it => it.Tag).ToList(), tts);
, но я не уверен, как еще я мог бы получить эту информацию.