获取投射到新类型的不同实体的列表,其中包含额外的计数字段

时间:2012-04-27 10:34:18

标签: entity-framework-4 linq-to-entities

我正在设计一个界面,用户可以在其中加入一个关键字的公告,当他们这样做时,我想建议通常与所选关键字一起出现的其他关键字。诀窍是将相关频率与建议关键字的属性一起使用。

关键字类型(EF)包含以下字段:

int Id
string Text
string UrlString

......以及与出版物实体集的多对多关系 我快到了。随着:

var overlappedKeywords =
            selectedKeyword.Publications.SelectMany(p => p.Keywords).ToList();

这里我得到了一些非常有用的东西:一个扁平的关键字列表,每个关键字都在列表中重复,但很多时候它与selectedKeyword一起出现。

剩余的挑战:
因此,我希望计算每个关键字在此列表中出现的次数,并将不同的关键字实体投影到名为KeywordCounts的新类型上,该类型与关键字具有相同的字段,但还有一个字段:int PublicationsCount,我将在其中填充overlappedKeywords中每个关键字的计数。 我该怎么做?

到目前为止,我尝试了两种方法:

var keywordCounts = overlappingKeywords
    .Select(oc => new KeywordCount
        {
            KeywordId = oc.Id,
            Text = oc.Text,
            UrlString = oc.UrlString,
            PublicationsCount = overlappingKeywords.Count(ok2 => ok2.Id == oc.Id)
        })
    .Distinct();

... PublicationsCount正在填充,但是Distinct在这里不起作用。 (必须我为此创建了一个EqualityComarer?为什么默认的EqualityComarer不起作用?)

var keywordCounts = overlappingKeywords
    .GroupBy(o => o.Id)
    .Select(c => new KeywordCount
        {
            Id = ???
            Text = ???
            UrlString = ???
            PublicationsCount = ???
        })

我对GroupBy不是很清楚。我似乎没有任何访问“选择”中的“o”,并且c不符合关键字的任何属性

更新
我的第一种方法适用于传递给.Distinct()的简单EqualityComparer:

class KeywordEqualityComparer : IEqualityComparer<KeywordCount>
{
    public bool Equals(KeywordCount k1, KeywordCount k2)
    {
        return k1.KeywordId== k2.KeywordId;
    }

    public int GetHashCode(KeywordCount k)
    {
        return k.KeywordId.GetHashCode();
    }
}

......但Slauma的答案更可取(并被接受)因为它不需要这个。我仍然难以理解为EF实体实例的默认EqualityComparer是什么 - 它不会仅仅根据主要ID进行比较,就像我在上面所做的那样?

1 个答案:

答案 0 :(得分:1)

你第二次尝试是更好的方法。我认为完整的代码是:

var keywordCounts = overlappingKeywords
    .GroupBy(o => o.Id)
    .Select(c => new KeywordCount
    {
        Id = c.Key, 
        Text = c.Select(x => x.Text).FirstOrDefault(),
        UrlString = c.Select(x => x.UrlString).FirstOrDefault(),
        PublicationsCount = c.Count()
    })
    .ToList();

这是对象的LINQ,我想,因为似乎没有涉及EF上下文而是对象overlappingKeywords,所以分组发生在内存中,而不是在数据库中。