上下文:我有一个Items表,每个表都有一组称为Tags的动态描述符多对多。每个Tag都属于一个TagType,该Tag确定Item代表哪种信息(大小,颜色,形状等)。每个Tag每个TagType最多只能有一个Items

目标:我想显示我所有<th>TagTypes</th>的表,并在每行中都有一列,其中<td>Tags</td>Item的嵌套表具有空单元格,如果Tag没有表示该TagType

问题:Linq查询仅用5000 Items花费至少30秒。我期望有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);,但是我不确定我还怎么去获取这些信息。

最佳答案

您在OnGetItemsAsync中的查询不知道,DisplayItem构造函数中会发生什么,因此您查询返回整个Items集合,每个Item的ItemTag集合和每个ItemTag的Tag集合以及每个Tag的TagType集合,因此您带回很多不必要的数据。为了防止这种情况,您应该从查询中删除包含。
您还可以优化查询,这似乎是最慢的部分。每次在整个集合中搜索一个mach的FirstOrDefault。你可以试试

return tts.Select(tt => new DisplayTag(tt.Name, tags.Where(t=>t.TagTypeId==tt.Id).GroupBy(t=>t.TagTypeId).Select(tg=>tg.First()?.Value??" "))).ToList();


然后查询将返回TagTypeId的集合,而不必在整个集合中搜索第一个条目。

09-17 00:59