This is my Table:
PupilNutrition
Id PupilId NutritionId
1 10 100
2 10 101
My another table Nutrition:
Id Nutritioncategory BatchId NutritionRate NutritionId Operation
1 A 1 9000 100 1
2 B 1 5000 100 0
3 C 1 5000 100 1
4 D 2 6000 101 2
5 E 2 7000 101 2
6 F 2 8000 101 0
This is one field to store final Rate:
decimal Rate= 0;
Case 1: Operation field with Value 0 and Batch Id 1
Rate= Rate + NutritionRate(i.e 5000 because for batch id 1 with condition 0 only 1 record is there).
Case 2:Now for operation field with Value 1 and Batch Id 1
Here i want to sum up both the value i.e(10000 and 5000) but during addition if sum of both is greater than 10000 then just take 10000 else take sum like this:
if(9000 + 5000 > 10000)
Rate= 10000
else
Rate=Rate + (Addition of both if less than 10000).
Case 3:Now for operation field with Value 0 and Batch Id 2
Rate= Rate + NutritionRate(i.e 8000 because for batch id 1 with condition 0 only 1 record is there).
Case 4:Now for operation field with Value 2 and Batch Id 2
Here I will select Maximum value from Nutrition Rate field if there are 2 records:
Rate=Rate - (Maximum value from 6000 and 7000 so will take 7000).
My Class file:
public partial class PupilNutrition
{
public int Id { get; set; }
public int PupilId { get; set; }
public int NutritionId { get; set; }
}
public partial class Nutrition
{
public int Id { get; set; }
public string Nutritioncategory { get; set; }
public decimal NutritionRate { get; set; }
public Nullable<int> NutritionId { get; set; }
}
This is how i have Done:
batchId=1 or 2;//
List<int> NutritionId = db.PupilNutrition.Where(x => PupilId == 10).Select(c => c.NutritionId).ToList(); //output 100,101
var data = db.Nutrition.Where(x => x.BatchId == batchId && NutritionId.Contains(x.NutritionId.Value)).ToList();
I have tried like this but its a labour process:
var data1=data.where(t=>t.Operation==0);
Rate= Rate + data1.Sum(p => p.NutritionRate);
Similarly for Operation 1:
var data2=data.where(t=>t.Operation==1);
This is left because here i need to sum up 2 value if two records are there as shown in my above cases and if sum is greater than 10000 than select 10000 else select sum.
Similarly for Operation 2:
var data3=data.where(t=>t.Operation==2);
Rate= Rate - data3.Max(p => p.NutritionRate);
I think i have done a labour process as this can be done even in better way with linq query only i guess.
So can anybody help me to simplify this whole process in linq query or even some better way and provide solution for Operation Value 2 which is left?
Shortest is not always the best.
Personally, I think that single complex LINQ statement can be hard to read and hard to debug.
Here is what I would do:
public decimal CalculateRate(int pupilId, int batchId)
{
return db.Nutrition
.Where(x => x.BatchId == batchId && db.PupilNutrition.Any(y => y.PupilId == pupilId && y.NutritionId == x.NutritionId))
.GroupBy(x => x.Operation)
.Select(CalculateRateForOperationGroup)
.Sum();
}
public decimal CalculateRateForOperationGroup(IGrouping<int, Nutrition> group)
{
switch (group.Key)
{
case 0:
// Rate = Sum(x)
return group.Sum(x => x.NutritionRate);
case 1:
// Rate = Min(10000, Sum(x))
return Math.Min(10000, group.Sum(x => x.NutritionRate));
case 2:
// Rate = -Max(x)
return -group.Max(x => x.NutritionRate);
default:
throw new ArgumentException("operation");
}
}
Then you could use it as follows:
var rateForFirstBatch = CalculateRate(10, 1);
var rateForSecondBatch = CalculateRate(10, 2);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With