取一个并跳过子表中的其他重复项

时间:2018-10-16 16:38:18

标签: linq entity-framework-core ef-core-2.1

我有一个项目列表,每个项目都有一些列表,现在我想选择子项的不同项目。我已经尝试过如下操作,但是不起作用。

var items = await _context.Items.
Include(i => i.Tags.Distinct()).
Include(i => i.Comments).
OrderBy(i => i.Title).ToListAsync();

//Tag items
TagId    -   tag
------------------
  1   ---   A 
  2   ---   B 
  3   ---   B 
  4   ---   C 
  5   ---   D 
  6   ---   D 
  7   ---   F
//Expected Result
Item.Tags -> [A,B,C,D,F]

如何在EF Core中做到这一点?谢谢。

3 个答案:

答案 0 :(得分:1)

您可以使用MoreLinq库获取DistinctBy或使用this post编写自己的库。

然后使用此:

var items = await _context.Items.
    Include(i => i.Tags).
    Include(i => i.Comments).
    OrderBy(i => i.Title).
    DistinctBy(d => d.Tags.tag).
    ToListAsync();

您希望基于一列获取不同的记录;因此应该这样做。

答案 1 :(得分:1)

显然,您有一个Items表,其中每个Item都有零个或多个Tags。此外,Items具有属性Comments,我们不知道它是一个字符串还是零个或多个字符串的集合。此外,每个Item都有一个Title

现在,您需要项的所有属性,每个属性都具有其Comments,以及项的唯一Tags列表。由Title

排序

数据库查询的最慢部分之一是将所选数据从数据库管理系统传输到本地进程。因此,将数据量限制在实际使用的最少数量是明智的。

Tags中的Items似乎在单独的表中。每个Item都有零个或多个Tags,每个Tag恰好属于一项。具有外键Tag.ItemId的简单一对多关系。

如果ItemId的数量为1000,Tags,则说明您知道这1000 Tags中的每一个都有一个外键ItemId,知道它的值是300。如果将所有这些外键都传送到本地进程,那将是一种浪费。

  

每当查询数据进行检查时,仅Select个属性   您真的打算使用。如果您打算更新Include,请仅使用var query = myDbContext.Items .Where(item => ...) // only if you do not want all items .OrderBy(item => item.Title) // if you Sort here and do not need the Title // you don't have to Select it .Select(item => new { // select only the properties you plan to use Id = item.Id, Title = item.Title, Comments = item.Comments, // use this if there is only one item, otherwise Comments = item.Comments // use this version if Item has zero or more Comments .Where(comment => ...) // only if you do not want all comments .Select(comment => new { // again, select only the Comments you plan to use Id = comment.Id, Text = comment.Text, // no need for the foreign key, you already know the value: // ItemId = comment.ItemId, }) .ToList(); Tags = item.Tags.Select(tag => new { // Select only the properties you need Id = tag.Id, Type = tag.Type, Text = tag.Text, // No need for the foreign key, you already know the value // ItemId = tag.ItemId, }) .Distinct() .ToList(), }); var fetchedData = await query.ToListAsync();   包含的项目。

因此您的查询将是:

VertexBufferObjects

答案 2 :(得分:0)

我还没有尝试过,但是我会说您将.Distinct()放在错误的位置。

var items = await _context.Items
        .Include(i => i.Tags)
        .Include(i => i.Comments).
        .OrderBy(i => i.Title)
        .Select(i => { i.Tags = i.Tags.GroupBy(x => x.Tag).Select(x => x.First()); return i; })
        .ToListAsync();