C# 对项目进行分类并按级别进行分组

C# 对项目进行分类并按级别进行分组,c#,entity-framework,linq-to-entities,C#,Entity Framework,Linq To Entities,我使用的是实体框架6,我有以下Linq查询: IDictionary<BodyMassIndexLevel, Int32> bmistats = context.Evaluations // Get all evaluations where Height and Weight measures were done .Where(x => x.Height != null && x.Weight != null) //

我使用的是实体框架6,我有以下Linq查询:

  IDictionary<BodyMassIndexLevel, Int32> bmistats = 
    context.Evaluations

    // Get all evaluations where Height and Weight measures were done
    .Where(x => x.Height != null && x.Weight != null)

    // Select the date of the evaluation, the worker id and calculate BMI
    .Select(x => new { Date = x.Date, Worker = x.Worker.Id, BMI = x.Weight.Value / Math.Pow(x.Height.Value / 100, 2) })

    // Group by worker
    .GroupBy(x => x.Worker)

    // Get the most recent evaluation for each worker and so the most recent BMI
    .Select(x => x.OrderByDescending(y => y.Date).Select(y => new { BMI = y.BMI }).FirstOrDefault())

    // Cache the result in memory
    .ToList()

    // Count the number of BMIS in each level
    .With(z =>
      new Dictionary<BodyMassIndexLevel, Int32> {
        { BodyMassIndexLevel.SevereThinness, z.Count(w => w.BMI < 16) },
        { BodyMassIndexLevel.MildThinness, z.Count(w => w.BMI >= 16 && w.BMI < 17) },
        { BodyMassIndexLevel.ModerateThinness, z.Count(w => w.BMI >= 17 && w.BMI < 18.5) },
        { BodyMassIndexLevel.Normal, z.Count(w => w.BMI >= 18.5 && w.BMI < 25) },
        { BodyMassIndexLevel.PreObese, z.Count(w => w.BMI >= 25 && w.BMI < 30) },
        { BodyMassIndexLevel.ObeseClassI, z.Count(w => w.BMI >= 30 && w.BMI < 35) },
        { BodyMassIndexLevel.ObeseClassII, z.Count(w => w.BMI >= 35 && w.BMI < 40) },
        { BodyMassIndexLevel.ObeseClassIII, z.Count(w => w.BMI >= 40) }
      }
    );
IDictionary bmists=
背景.评价
//获取所有已完成身高和体重测量的评估
.其中(x=>x.高度!=null和&x.重量!=null)
//选择评估日期、员工id并计算BMI
.Select(x=>new{Date=x.Date,Worker=x.Worker.Id,BMI=x.Weight.Value/Math.Pow(x.Height.Value/100,2)})
//按工人分组
.GroupBy(x=>x.Worker)
//获取每位员工的最新评估结果以及最新BMI
.Select(x=>x.OrderByDescending(y=>y.Date)。Select(y=>new{BMI=y.BMI})。FirstOrDefault()
//将结果缓存在内存中
托利斯先生()
//计算每个级别的BMI数量
.With(z=>
新词典{
{BodyMassIndexLevel.SevereThinness,z.Count(w=>w.BMI<16)},
{BodyMassIndexLevel.MildThinness,z.Count(w=>w.BMI>=16&&w.BMI<17)},
{BodyMassIndexLevel.mediatethinness,z.Count(w=>w.BMI>=17&&w.BMI<18.5)},
{BodyMassIndexLevel.Normal,z.Count(w=>w.BMI>=18.5&&w.BMI<25)},
{BodyMassIndexLevel.PreObese,z.Count(w=>w.BMI>=25&&w.BMI<30)},
{BodyMassIndexLevel.obeseclasssi,z.Count(w=>w.BMI>=30&&w.BMI<35)},
{BodyMassIndexLevel.ObeseClassII,z.Count(w=>w.BMI>=35&&w.BMI<40)},
{BodyMassIndexLevel.ObeseClassIII,z.Count(w=>w.BMI>=40)}
}
);
我有两个问题:

  • 是否有可能提高此查询的性能

  • 我是否可以将级别中的计数部分移动到查询中,这样就没有ToList()

  • 比如说

  • 之后做一些类似于截断体重指数的事情 //选择评估日期、员工id并计算BMI
  • 创建BMILevel表,其中列(BMILevelName | BMIValues)包含以下行(BodyMassindXlevel.ModerateThinness,17),(BodyMassindXlevel.PreObese,25),(BodyMassindXlevel.PreObese,26)等
  • 通过query.BMI=BMILevel.BMIValue
    上的*BMILevel*表,而不是
    GroupBy BMILevel.BMILevelName
    将您的select查询连接到所有组的
    Count
  • 或者,您可以使用包含以下行的列(BMILevelName | BMIValueBeginInterval,BMIValueEndInterval)来定义BMILevel(BodyMassIndexLevel.ModerateThinness,17,18),(BodyMassIndexLevel.PreObese,25,30)

    从而表现出

    query JOIN BMILevel ON query.BMI BETWEEN BMILevel.BMIValueBeginInterval AND BMILevel.BMIValueEndInterval
    

    我认为EF可以转换“in”。(或)正确调用< /P>


    更新: 如果不想创建另一个表,可以尝试在内存中创建示例类型的对象列表

    class BMILevel {
       public BMILevelEnum BMILevelName {get;set;}
       public double BMILevelValueBeginInterval {get;set;}
       public double BMILevelValueEndInterval {get;set;}
    }
    
    然后创建内存中的集合:

    var bmiLevels = new List<BMILevel> { new BMILevel {...}, ... }
    
    var bmiLevels=new List{new BMILevel{…},…}
    
    按照我上面描述的方式使用它。 我不知道EF 6有多好,但旧版本无法处理非实体的操作(它无法将表达式转换为正确的SQL),因此它会导致效率低下的查询或错误


    加快查询执行速度的唯一方法是将其委托给SQL server。您可以使用EF功能,因此可能需要创建新表。另一种方法-使用ADO.NET(SqlCommand、SqlConnection等)并绕过EF进行操作。

    对不起,你能给我举一个(1)的例子吗?我不知道你的意思。关于其余部分,我希望避免在数据库中为BMILevels创建一个表。我的意思是.Select(x=>new{Date=x.Date,Worker=x.Worker.Id,BMI=Math.Truncate(x.Weight.Value/Math.Pow(x.Height.Value/100,2)),但这只是一种在相等条件下进行连接的方法。但它仍然需要在数据库中创建新表。