使用linq查询简化流程

Lea*_*sed 19 c# linq asp.net-mvc performance

这是我的表:

PupilNutrition

Id     PupilId   NutritionId
1       10          100  
2       10          101
Run Code Online (Sandbox Code Playgroud)

我的另一张桌子营养:

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          
Run Code Online (Sandbox Code Playgroud)

这是存储最终费率的一个字段:

decimal Rate= 0;
Run Code Online (Sandbox Code Playgroud)

案例1:值为0且批次为1的操作字段

 Rate= Rate + NutritionRate(i.e 5000 because for batch id 1 with condition 0 only 1 record is there).
Run Code Online (Sandbox Code Playgroud)

情况2:现在为具有值1和批次标识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).
Run Code Online (Sandbox Code Playgroud)

情况3:现在为具有值0和批次标识2的操作字段

 Rate= Rate + NutritionRate(i.e 8000 because for batch id 1 with condition 0 only 1 record is there).
Run Code Online (Sandbox Code Playgroud)

情况4:现在为具有值2和批次标识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).
Run Code Online (Sandbox Code Playgroud)

我的班级文件:

 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; }
    }
Run Code Online (Sandbox Code Playgroud)

这就是我完成的方式:

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();
Run Code Online (Sandbox Code Playgroud)

我试过这样但是它是一个劳动过程:

var data1=data.where(t=>t.Operation==0);
Rate= Rate + data1.Sum(p => p.NutritionRate);
Run Code Online (Sandbox Code Playgroud)

与操作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.
Run Code Online (Sandbox Code Playgroud)

同样对于行动2:

var data3=data.where(t=>t.Operation==2);
Rate= Rate - data3.Max(p => p.NutritionRate);
Run Code Online (Sandbox Code Playgroud)

我认为我已经完成了一个劳动过程,因为我可以通过linq查询以更好的方式完成.

那么任何人都可以帮我简化linq查询中的整个过程,甚至更好的方法,并为剩下的操作值2提供解决方案吗?

Kas*_*ols 11

最短并不总是最好的.

就个人而言,我认为单个复杂的LINQ语句可能难以阅读且难以调试.

这是我要做的:

    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");
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后你可以使用它如下:

var rateForFirstBatch = CalculateRate(10, 1);
var rateForSecondBatch = CalculateRate(10, 2);
Run Code Online (Sandbox Code Playgroud)


Nie*_*s V 5

通过以下方式更容易与小组:

int sumMax = 10000;
var group = from n in nutrition
    group n by new { n.Operation, n.BatchId } into g
    select new { BatchId = g.Key.BatchId, 
        Operation = g.Key.Operation, 
        RateSum = g.ToList().Sum(nn => nn.NutritionRate), 
        RateSumMax = g.ToList().Sum(nn => nn.NutritionRate) > sumMax ? sumMax : g.ToList().Sum(nn => nn.NutritionRate), 
        RateMax = g.ToList().Max(nn => nn.NutritionRate) };
var result = from g in group
    select new {
        BatchId = g.BatchId,
        Operation = g.Operation,
        Rate = g.Operation == 1 ? g.RateSumMax :
               g.Operation == 2 ? g.RateMax :
               g.RateSum //default is operation 0
    };
var totalRate = result.Sum(g=>g.Rate);
Run Code Online (Sandbox Code Playgroud)