在 child table 中取一个并跳过其他重复项
Take one and skip other duplicate item in a child table
我有一个项目列表,每个项目都有一些列表,现在我想要 select child 个不同的项目。我试过如下,但没有用。
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 中执行此操作?谢谢
您可以使用 MoreLinq library to get DistinctBy
or write your own using 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();
您想根据一列获得不同的记录;所以应该这样做。
显然你有 Items
个 table,其中每个 Item
有零个或多个 Tags
。此外 Items
有一个 属性 Comments
,我们不知道它是一个字符串,还是零个或多个字符串的集合。此外,每个 Item
都有一个 Title
.
现在您需要项目的所有属性,每个属性都有其 Comments
,以及项目的唯一 Tags
列表。由 Title
订购
数据库查询中速度较慢的部分之一是将所选数据从数据库管理系统传输到本地进程。因此,明智的做法是将数据量限制在您实际使用的最低限度。
Items
的 Tags
似乎在单独的 table 中。每个 Item
有零个或多个 Tags
,每个 Tag
只属于一个项目。带有外键 Tag.ItemId
.
的简单一对多关系
如果Item
和Id
300有1000个Tags
,那么就知道这1000个Tags
每一个都有一个外键ItemId
你知道它的值为 300。如果你将所有这些外键传输到你的本地进程,那真是浪费。
Whenever you query data to inspect it, Select
only the properties
you really plan to use. Only use Include
if you plan to update the
included item.
因此您的查询将是:
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();
我没试过,但我会说你把 .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();
我有一个项目列表,每个项目都有一些列表,现在我想要 select child 个不同的项目。我试过如下,但没有用。
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 中执行此操作?谢谢
您可以使用 MoreLinq library to get DistinctBy
or write your own using 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();
您想根据一列获得不同的记录;所以应该这样做。
显然你有 Items
个 table,其中每个 Item
有零个或多个 Tags
。此外 Items
有一个 属性 Comments
,我们不知道它是一个字符串,还是零个或多个字符串的集合。此外,每个 Item
都有一个 Title
.
现在您需要项目的所有属性,每个属性都有其 Comments
,以及项目的唯一 Tags
列表。由 Title
数据库查询中速度较慢的部分之一是将所选数据从数据库管理系统传输到本地进程。因此,明智的做法是将数据量限制在您实际使用的最低限度。
Items
的 Tags
似乎在单独的 table 中。每个 Item
有零个或多个 Tags
,每个 Tag
只属于一个项目。带有外键 Tag.ItemId
.
如果Item
和Id
300有1000个Tags
,那么就知道这1000个Tags
每一个都有一个外键ItemId
你知道它的值为 300。如果你将所有这些外键传输到你的本地进程,那真是浪费。
Whenever you query data to inspect it,
Select
only the properties you really plan to use. Only useInclude
if you plan to update the included item.
因此您的查询将是:
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();
我没试过,但我会说你把 .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();