我正在使用Entity Framework 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) }
}
);
我有两个问题:
是否可以提高此查询的效果?
我可以将计数部分的级别移动到查询中,因此没有ToList()吗?
答案 0 :(得分:0)
例如
JOIN your select query with *BMILevel* table on query.BMI = BMILevel.BMIValue
,而不是GroupBy BMILevel.BMILevelName
,最后是Count
所有群组。或者,您可以使用包含(BodyMassIndexLevel.ModerateThinness,17,18),(BodyMassIndexLevel)等行的列(BMILevelName | BMIValueBeginInterval,BMIValueEndInterval)定义 BMILevel 。 PreObese,25,30)。
然后执行
query JOIN BMILevel ON query.BMI BETWEEN BMILevel.BMIValueBeginInterval AND BMILevel.BMIValueEndInterval
我认为EF可以改变&#39;&#39;&#39;&amp;&amp;&#39;&#39;&gt;&#39;在.Where()(或加入)中正确调用
如果您不想创建另一个表,您可以尝试创建样本类型对象的内存中列表
class BMILevel {
public BMILevelEnum BMILevelName {get;set;}
public double BMILevelValueBeginInterval {get;set;}
public double BMILevelValueEndInterval {get;set;}
}
而不是创建内存中的集合:
var bmiLevels = new List<BMILevel> { new BMILevel {...}, ... }
以我上面描述的方式使用它。 我不知道EF 6有多好,但旧版本无法处理非实体操作(它无法将表达式转换为正确的SQL),因此导致查询效率低下或错误。
更快地执行查询的唯一方法是将其委派给SQL Server。您可以使用EF功能,因此可能需要创建新表。另一种方法 - 使用ADO.NET(SqlCommand,SqlConnection等)并绕过EF。