对范围进行分类

时间:2014-09-05 15:52:17

标签: c# entity-framework

我的枚举如下:

public enum BPLevel {
  Normal = 1,
  HighNormal = 2,
  HypertensionStage1 = 3,
  ModerateHypertensionStage2 = 4,
  SeverHypertensionStage3 = 5,
} // BloodPressureLevel

我有以下分类:

Classification table

我正在使用实体框架,我需要计算每个级别中有多少人:

IDictionary<BPLevel, Int32> stats = context
  .Persons
  .Select(x => new { PersonId = x.Person.Id, BPDiastolic = x.BPDiastolic, BPSystolic = x.BPSystolic })
  .Count( ...

我的问题是如何在我的查询中应用此分类?

6 个答案:

答案 0 :(得分:1)

我只想添加一个分配给函数调用结果的分类成员

IDictionary<BPLevel, Int32> stats = context
  .Persons
  .Select(x => new { PersonId = x.Person.Id, BPDiastolic = x.BPDiastolic, 
                     BPSystolic = x.BPSystolic, 
                     Classification = GetClassification(BPDiastolic, BPSystolic) })
  .Count( ...

BPLevel GetClassification(int diastolic, int systolic)
{
    ...
}

对EF的查询有时候不喜欢在查询中发生的操作,因此您可能需要在ToList之前执行Select以将其放入内存(因此其对象的LINQ)

答案 1 :(得分:0)

我会在你的类中编写一个私有静态辅助函数,为你做分类并在你的投影中插入对该函数的调用。类似的东西:

private static BPLevel ClassifyBP(int diastolic, int systolic) {
  // Appropriate switch statement here
}

然后您的选择投影看起来像:

.Select(x => new { PersonId = x.Person.Id,
                   BPDiastolic = x.BPDiastolic, 
                   BPSystolic = x.BPSystolic, 
                   BPLevel = ClassifyBP(x.BPDiastolic, x.BPSystolic) })

答案 2 :(得分:0)

使用GroupBy语句,您可以将所有人分类到各自的BPLevel,您只需要执行ToDictionary并计算每个类别中的人数。因此

IDictionary<BPLevel, Int32> stats = context
  .Persons
  .Select(x => new { PersonId = x.Person.Id, BPDiastolic = x.BPDiastolic, BPSystolic = x.BPSystolic })
  .AsEnumerable()  // I'm not completely familiar with Entity Framework, so this line may be necessary to force evaluation to continue in-memory from this point forward
  .GroupBy(p => ... // Test which returns a BPLevel)
  .ToDictionary(g => g.Key, g => g.Count());

答案 3 :(得分:0)

我在这种情况下做的是在Person

中制作一个帮助属性
public BPLevel BpLevel 
{
    get
    {
        if(Systolic >= 180)
            return BPLevel.SeverHypertensionStage3
        else if
           ...
    }
}

然后我按

分组
.ToList()   // you need to execute against the DB before you call the helper property
.GroupBy(x => x.BPLevel) 
.Select(x => /*moar data transformation
               x is a collection of Person
               x.Key, is the BPLevel*/ )

确保你执行ToList()部分,否则在尝试将helper属性转换为SQL时可能会得到一个不受支持的异常

答案 4 :(得分:0)

另一种选择是选择具有BPLevel属性getter的具体类,为您进行分类:

public class PersonWithBP {

  // other properties

  public BPLevel BPClassification {
    get { 
      // logic to calculate BPLevel
      return bpLevel;
   }

}

现在你的选择变为

.Select(x => new PersonWithBP() {}

答案 5 :(得分:0)

这不太好,但是计数查询将在数据库中执行。

var stats = context.Persons
    .Select(x => new 
    {
        Level = x.BPDiastolic < 85 && x.BPSystolic < 130
            ? BPLevel.Normal
            : (x.BPDiastolic < 90 && x.BPSystolic < 140
                ? BPLevel.HighNormal
                : (x.BPDiastolic < 100 && x.BPSystolic < 160
                    ? BPLevel.HypertensionStage1)
                    : (x.BPDiastolic < 110 && x.BPSystolic < 180
                        ? BPLevel.ModerateHypertensionStage2
                        : BPLevel.SeverHypertensionStage3)))

    })
    .GroupBy(x => x.Level)
    .ToDictionary(x => x.Key, g => g.Count()) // execute in database
    .Union(Enum.GetValues(typeof(BPLevel))
        .OfType<BPLevel>()
        .ToDictionary(x => x, x => 0)) // default empty level
    .GroupBy(x => x.Key)
    .ToDictionary(x => x.Key, x => x.Sum(y => y.Value)); // combine both