使用linq检索基于其他列值的行值

时间:2018-08-31 08:35:28

标签: c# linq

我有三个数据表,基本上包含以下数据:

表1:

ID      FContractID     | WaitingTime
1   |   1       |       85
2   |   1       |       98
3   |   1       |       122
4   |   1       |       45
5   |   1       |       234
6   |   1       |       101

表2:

PricingCriterionItemId  PricingCriterionName        PricingCriterionUnit
1                   |   WaitingTimeMax          |   min
2                   |   WaitingTimePeriod       |   min
3                   |   WaitingTimeOverdue      |   €/period
4                   |   OverDuePriceMax         |   €

表3:

PricingCriterionId      ContractID      PricingCriterionItemId      PricingCriterionValue
1                   |   1           |   1                       |   70
2                   |   1           |   2                       |   30
3                   |   1           |   3                       |   30,00
4                   |   1           |   4                       |   120,00

我想在表1中添加一列,其中包含等待时间成本。等待时间成本的计算方式如下:

WaitingTimeCost = min(((WaitingTime - WaitingTimeMax) / WaitingTimePeriod) * WaitingTimeOverdue, OverDuePriceMax)

我可以轻松地将表2和3合并为一个表:

表4

PricingCriterionId      ContractID      PricingCriterionName        PricingCriterionValue       PricingCriterionUnit
1                   |   1           |   WaitingTimeMax          |       70                      |   min
2                   |   1           |   WaitingTimePeriod       |   30                      |   min
3                   |   1           |   WaitingTimeOverdue      |   30,00                   |   €/period
4                   |   1           |   OverDuePriceMax         |   120,00                  |   €

是否可以使用linq使用其他列的值在某一行上分配列的值?

类似

  var result = from WaitingData in table1
                join PricingCriteria in table4 
                on WaitingData.ContractId equals PricingCriteria.ContractId
                let WaitingTimeMax = (select PricingCriterionValue from table4 where PricingCriterionName = "WaitingTimeMax")
                let ...
                let WaitingTimeCost = min(((WaitingTime - WaitingTimeMax) / WaitingTimePeriod) * WaitingTimeOverdue, OverDuePriceMax)
                select new
                {
                    ID,
                    WaitingTimeCost
                }

如何使用linq正确地表达这一点?

1 个答案:

答案 0 :(得分:0)

您不需要执行数据库查询中的所有操作。
数据库只是IO设备,仅负责读写数据。

加载所有必需的数据并计算。

var contractsId = waitingData.Select(data => data.ContractId).ToList();
var pricingCriterias = table4.Where(criteria => contractsId.Contains(criteria.ContractId)
                             .ToLookup(criteria => criteria.ContractId);

var maxWaitingTime = 
    pricingCriterias.SelectMany(group => group)
                    .Where(criteria => criteria.PricingCriterionName = "WaitingTimeMax")
                    .Max(criteria => criteria.PricingCriterionValue);

foreach (var waitingItem in waitingData)
{
    // Calculate others waiting values

    var waitingPerPeriod = (WaitingTime - maxWaitingTime) / WaitingTimePeriod);
    var waitingPrice = waitingPerPeriod * WaitingTimeOverdue;
    var WaitingTimeCost = Math.Min(waitingPrice, OverDuePriceMax)
}

下面是DataTables的示例。
但是DataTable很重,不是强类型的数据结构,而作为开发人员,则需要更多时间来处理它。

相反,将DataTable中的数据转换为具有描述性属性名称的普通强类型对象-您将免费获得IntelliSense;)

var contractsId = 
    waitingData.AsEnumerable()
               .Select(row => row.Field<int>("ContractId"))
               .ToList();
var pricingCriterias = 
    table4.AsEnumerable()
          .Where(row => contractsId.Contains(row => row.Field<int>("ContractId"))
          .ToLookup(row => row.Field<int>("ContractId"));

var maxWaitingTime = 
    pricingCriterias.SelectMany(group => group)
                    .Where(row => row.Field<string>("PricingCriterionName") = "WaitingTimeMax")
                    .Max(row => row.Field<int>("PricingCriterionValue"));

foreach (var waitingItem in waitingData)
{
    // Calculate others waiting values

    var waitingPerPeriod = (WaitingTime - maxWaitingTime) / WaitingTimePeriod);
    var waitingPrice = waitingPerPeriod * WaitingTimeOverdue;
    var WaitingTimeCost = Math.Min(waitingPrice, OverDuePriceMax)
}