C# 使用linq查询简化流程
这是我的桌子: 婴儿营养C# 使用linq查询简化流程,c#,asp.net-mvc,performance,linq,C#,Asp.net Mvc,Performance,Linq,这是我的桌子: 婴儿营养 Id PupilId NutritionId 1 10 100 2 10 101 我的另一张桌子营养: Id Nutritioncategory BatchId NutritionRate NutritionId Operation 1 A 1 9000 100 1 2
Id PupilId NutritionId
1 10 100
2 10 101
我的另一张桌子营养:
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
decimal Rate= 0;
这是一个用于存储最终速率的字段:
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
decimal Rate= 0;
案例1:值为0且批次Id为1的操作字段
Rate= Rate + NutritionRate(i.e 5000 because for batch id 1 with condition 0 only 1 record is there).
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).
案例2:现在用于值为1且批次Id为1的操作字段
Rate= Rate + NutritionRate(i.e 5000 because for batch id 1 with condition 0 only 1 record is there).
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).
案例3:现在用于值为0且批次Id为2的操作字段
Rate= Rate + NutritionRate(i.e 8000 because for batch id 1 with condition 0 only 1 record is there).
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).
案例4:现在用于值为2且批次Id为2的操作字段
Rate= Rate + NutritionRate(i.e 8000 because for batch id 1 with condition 0 only 1 record is there).
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).
我的类文件:
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; }
}
同样,对于操作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.
类似地,操作2:
var data3=data.where(t=>t.Operation==2);
Rate= Rate - data3.Max(p => p.NutritionRate);
我想我已经完成了一个劳动过程,因为这可以通过linq查询以更好的方式完成
那么,有谁能帮助我在linq查询中简化整个过程,或者提供更好的方法,为剩下的操作值2提供解决方案呢?更新
此查询看起来应该可以为您完成任务。注意,我还没有测试过它,所以可能有一两个语法错误,但这个想法似乎是正确的
var rate = db.Nutrition
.GroupBy(n => new { n.BatchId, n.Operation })
.Select(g => g.Sum(n => n.NutritionRate) > 10000 ? 10000 : g.Sum(n => n.NutritionRate))
.Sum();
或者,如果要查询每个“案例”:
rate = db.Nutrition
.Where(n => n.BatchId == 1 && n.Operation == 0)
.Sum(n => n.NutritionRate); //Case 1
rate += Math.Min(
10000, //Either return 10,000, or the calculation if it's less than 10,000
db.Nutrition
.Where(n => n.BatchId == 1 &&
n.Operation == 1) //filter based on batch and operation
.Sum(n => n.NutritionRate) //take the sum of the nutrition rates for that filter
); //Case 2
rate += db.Nutrition
.Where(n => n.BatchId == 2 && n.Operation == 0)
.Sum(n => n.NutritionRate); //Case 3
rate += Math.Min(
10000, //Either return 10,000, or the calculation if it's less than 10,000
db.Nutrition
.Where(n => n.BatchId == 2 &&
n.Operation == 2) //filter based on batch and operation
.Sum(n => n.NutritionRate) //take the sum of the nutrition rates for that filter
); //Case 4
通过以下方式更轻松地进行分组:
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);
最短并不总是最好的 就我个人而言,我认为单个复杂的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");
}
}
试试这个。我打断了这个查询以澄清问题,但您只能将其合并到一个语句中
//// Join the collection to get the BatchId
var query = nutritionColl.Join(pupilNutrition, n => n.NutritionId, p => p.NutritionId, (n, p) => new { BatchId = p.Id, Nutrition = n });
//// Group by BatchId, Operation
var query1 = query.GroupBy(i => new { i.BatchId, i.Nutrition.Operation });
//// Execute Used cases by BatchId, Operation
var query2 = query1.Select(grp =>
{
decimal rate = decimal.MinValue;
if (grp.Count() == 1)
{
rate = grp.First().Nutrition.NutritionRate;
}
else if (grp.First().BatchId == 1)
{
var sum = grp.Sum(i => i.Nutrition.NutritionRate);
rate = sum > 10000 ? 10000 : sum;
}
else
{
rate = grp.Max(i => i.Nutrition.NutritionRate);
}
return new { BatchId = grp.First().BatchId, Operation = grp.First().Nutrition.Operation, Rate = rate };
}
);
//// try out put
foreach (var item in query2)
{
Console.WriteLine("{0} {1} {2} ", item.Operation, item.BatchId, item.Rate);
}
希望有帮助请澄清-您想要4个不同的结果,还是一个结果,即案例1+案例2+案例3+案例4?@Rob:最终结果如下:案例1(费率)+案例2(费率)+案例3(费率)。只有3个条件是0,1,2。可以像Niels V那样在一个linq查询中完成,因为我想最小化计算步骤,所以您没有将我的条件(0,1,2)考虑到您的查询中的考虑因素,例如0何时会出现,1何时会出现,2何时会出现(最大值)我在答案中添加了条件,但我不确定我是否理解您的处理要求(这就是为什么我首先忽略这些要求)。您在上一次查询中检查的条件需要在第一次查询中检查。在执行求和或选择最大值之前,您需要检查运算值是0、1还是2。例如:RateSum=g。条件==1?g、 ToList().Sum(nn=>nn.NutritionRate).OP表示需要减去最大值,而不是相加。您应该使用
grp.Key.BatchId
而不是grp.First()。BatchId
OP表示需要减去最大值,而不是相加。它应该是rate=-grp.Max(i=>i.Nutrition.NutritionRate)代码>@Kaspars Ozols我建议您仔细阅读该声明。“在这里,如果有两条记录,我将从营养率字段中选择最大值:比率=比率-(6000和7000之间的最大值,因此将取7000)”他从哪里挑选7000?我再次阅读了这条语句,它非常有意义。有两条记录通过batchId=2和option=2进行匹配。一个是6000,另一个是7000。选择最大值并从总速率中减去。你期望在-ve中有多少利率。其次,我认为它是连字符-
而不是负号。它不允许我这样使用:。Select(CalculateRateForOperationGroup)您可以指定确切的错误消息吗?我可以在我的机器上运行这个代码。您可以尝试用替换。选择(CalculateRateForOperationGroup)
。选择(x=>CalculateRateForOperationGroup(x))