2014-09-05 3 views
4

У меня есть перечисление следующим образом:значения классифицируют по диапазонам

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

И у меня есть следующая классификация:

Classification table

Я использую Entity Framework и мне нужно подсчитать, сколько людей являются на каждом уровне:

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

Моя проблема заключается в том, как я могу применить этот cl в моем запросе?

+0

Можете ли вы опубликовать членов класса 'context.Persons'? –

ответ

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

Я был бы рад услышать от downvoter, какая у них проблема с моим подходом/сообщением. – BradleyDotNET

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) }) 
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()); 
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() часть, иначе вы можете получить не поддерживаемое исключение, когда оно пытается преобразовать ваше вспомогательное свойство в SQL.

0

Другим вариантом было бы выбрать в конкретный класс, который имеет свойство геттер BPLevel, что делает классификацию для вас:

public class PersonWithBP { 

    // other properties 

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

} 

Теперь ваш выбор становится

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

Это не очень, но запрос count будет выполнен в базе данных.

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 
Смежные вопросы