转换为字典并填充缺失的项目

时间:2014-09-05 14:09:55

标签: c# entity-framework

我的查询如下:

IDictionary<ClassificationLevel, Int32> stats = context.Exams
  .GroupBy(x => x.Classification)
  .Select(x => new { Key = x.Key, Count = x.Count() })
  // ... 

字典ClassificationLevel如下:

public enum ClassificationLevel { L1 = 1, L2 = 2, L3 = 3, L4 = 4 }

我的问题是:

  1. 如何将查询结果转换为IDictionary

  2. 计数0的项目不会出现在字典中。 如何确保这些项目的值为0。

  3. 已更新

    为了获得最佳性能,我认为应该做到以下几点:

    IDictionary<ClassificationLevel, Int32> stats = context.Exams
      .GroupBy(x => x.Classification)
      .ToDictionary(x => new { Key = x.Key, Count = x.Count() });
    

    这会关闭EF查询...

    然后我会找到哪些键丢失,例如缺少哪些ClassificationLevel项,并添加值为0的那些键。

    我该怎么做?

5 个答案:

答案 0 :(得分:1)

使用Enumerable.ToDictionary()然后Enum.GetValues()填写缺失的值:

        IDictionary<ClassificationLevel, Int32> dict = context.Exams
            .GroupBy(x => x.Classification)
            .ToDictionary(g => g.Key, g => g.Count());
        foreach (ClassificationLevel level in Enum.GetValues(typeof(ClassificationLevel)))
            if (!dict.ContainsKey(level))
                dict[level] = 0;

或者,如果实体框架在ToDictionary()处发布,我相信您可以执行以下操作:

        IDictionary<ClassificationLevel, Int32> dict = context.Exams
            .GroupBy(x => x.Classification)
            .Select(x => new { Key = x.Key, Count = x.Count() })
            .AsEnumerable()
            .ToDictionary(g => g.Key, g => g.Count);
        foreach (ClassificationLevel level in Enum.GetValues(typeof(ClassificationLevel)))
            if (!dict.ContainsKey(level))
                dict[level] = 0;

答案 1 :(得分:1)

使用单个linq表达式。

var stats = context.Exams
    .GroupBy(x => x.Classification)
    .ToDictionary(x => x.Key, g => g.Count()) // execute the query
    .Union(Enum.GetValues(typeof(ClassificationLevel))
        .OfType<ClassificationLevel>()
        .ToDictionary(x => x, x => 0)) // default empty count
    .GroupBy(x => x.Key) // group both
    .ToDictionary(x => x.Key, x => x.Sum(y => y.Value)); // and sum

答案 2 :(得分:0)

您可以在LINQ中使用"Left Outer Join",之后您可以使用GroupBy + ToDictionary

var query = from classification in Enum.GetValues(typeof(ClassificationLevel)).Cast<ClassificationLevel>()
            join exam in context.Exams on classification equals exam.Classification into gj
            from subExam in gj.DefaultIfEmpty()
            select new { classification, exam = subExam };
IDictionary<ClassificationLevel, Int32> stats = query
    .GroupBy(x => x.classification)
    .ToDictionary(g => g.Key, g => g.Count());

答案 3 :(得分:0)

你可以像这样解决它

var enumValues = Enum.GetValues(typeof (EnumType)).Cast<EnumType>().ToArray();
Enumerable.Range((int) enumValues.Min(), (int) enumValues.Max()).ToDictionary(
                        x => x.Key,
                        x => context.Exams.Count(e => e.Classification == x)
                        );

答案 4 :(得分:0)

此代码允许您循环枚举。     foreach(ClassificationLevel级别在(ClassificationLevel [])Enum.GetValues(typeof(ClassificationLevel)))     {     }

然后你可以在循环中间添加如下内容:

if(!stats.KeyExists(level))
{
   stats.Add(level, 0);
}