C# LINQ 联接与投影
本文关键字:投影 LINQ | 更新日期: 2023-09-27 17:56:13
所以在我的商店应用程序中,我允许用户收藏物品。我希望做的是在用户配置文件页面中显示收藏夹项目列表,其中列表按相同日期降序排序。
我们需要加入 2 个表,一个是项目,另一个是收藏夹。
如何连接这两个表,因此结果将回答以下条件:
-
结果将是此特定用户收藏的项目列表。
-
结果将附带每个项目的注释列表(每个项目都有一个注释列表)。
-
结果将正确排序。
到目前为止,我想出了这个:
Items =
await _context.Favorites
.Join(
_context.Items,
f => f.ItemId,
i => i.Id,
(f, i) => new { f, i })
.Distinct()
.OrderByDescending(x => x.f.FavDate)
.Select(x => x.i)
.Skip(skip).Take(take)
.Include(c => c.ListOfComments)
.ToListAsync();
这有效,但不回答第一个条件,即仅返回特定用户喜欢的项目,这将返回用户而不是特定用户喜欢的项目列表。
我试图在连接(_context之前添加一个where子句。Favorites.Where(f.UserVoterId.equals(profileId)),但它会抛出异常。
解决此问题的一种方法是:
- 包括用户 ID 作为连接键,并且
- 分步骤加载数据
要选择特定用户(profileId
)的收藏夹项目,您需要以下查询:
var favorites = _context.Favorites.OrderByDescending(f => f.FavDate)
.Join(_context.Items,
fav => new { fav.ItemId, UserId = fav.UserVoterId },
item => new { ItemId = item.Id, UserId = profileId },
(fav, item) => item)
.Skip(pageIndex * pageSize)
.Take(pageSize)
.ToList();
要加载评论,只需尝试以下方法之一(以有效者为准):
var itemIds = favorites.Select(f => f.Id);
var comments = _context.Comments.Where(c => itemIds.Contains(c.ItemId))
.GroupBy(c => c.ItemId)
.ToDictionary(g => g.Key, g => g.ToArray());
或
var items = _context.Comments
.GroupJoin(favorites,
comment => comment.ItemId,
favorite => favorite.Id,
(fav, comments) => new
{
Item = fav,
Comments = comment.ToArray()
});
在第一种情况下,注释将添加到Dictionary<TItemId, Comment>
其中TItemId
是item.Id
的类型,并获取您将使用的项目的注释
var itemComments = comments[item.Id];
这是一个O(1)
操作。
在第二种情况下,items
集合将包含您需要的所有数据,因此您必须将其投影到适合您需求的结构中。
注意,我之前提到过哪个有效,因为我不完全确定GroupJoin
是否正确转换为 SQL,并且我不确定我是否错过了 GroupJoin
方法的一些要求。