我有这两个实体(在 C# 和 EntityFramework 中):
public class Article
{
public int Id { get; set; }
public IList<Tag> Tags { get; set; }
}
public class Tag
{
public int Id { get; set; }
public IList<Article> Articles { get; set; }
}
具有n-n关系。我正在加载我的文章,就像您在这段代码中看到的那样简单:
var model = _context.Articles
.AsNoTracking()
.Include(a => a.Tags)
.ToList();
现在,我试图通过以下片段获取文章中重复次数最多的标签
:
var tags = model.SelectMany(a => a.Tags)
.GroupBy(t => new { t.Name, t.Articles })
.OrderByDescending(g => g.Count())
.Take(10);
但它似乎不起作用(我得到的所有标签的 Count = 1)。我在这里错过了什么?有什么想法吗?提前致谢。
回答您的具体问题:
But it seems doesn't work (I'm getting Count = 1 for all tags). What am I missing here?
这是因为您已将 tag.Articles
包含在分组键中。如果具有相同 Id
的 Tag
对象共享同一个实例,通常不会有问题(除了冗余和不必要的比较)。但是由于您已使用无跟踪查询 (.AsNoTracking()
) 填充了 model
,因此代表同一条记录的 Tag
对象实际上是不同的实例(数据重复),它们的 Articles
列表也是如此,因此 group by 无法按预期工作。可以通过以下代码片段轻松看出:
foreach (var tagGroup in model.SelectMany(a => a.Tags).GroupBy(t => t.Id))
{
Tag prevTag = null;
foreach (var tag in tagGroup)
{
if (prevTag != null) Debug.Assert(prevTag == tag); // FAIL!
prevTag = tag;
}
}
要解决此问题,请删除 AsNotracking
或从分组键中排除 Articles
:
var tags = model.SelectMany(a => a.Tags)
.GroupBy(t => t.Id) // or Name
.OrderByDescending(g => g.Count())
.Take(10);
我是一名优秀的程序员,十分优秀!