在 LINQ 中的 select 语句内执行计算

Perform calculation inside select statement in LINQ

我有一种情况,我必须计算两个值的百分比 例如

IEnumerable<RenewalModel> result = 
    from r in renewalLists
    group r by r.CityID into grpCity
    select new RenewalModel
    {
        CityID = grpCity.Key,
        City = (from g in grpCity where g.CityID == grpCity.Key select g.City).First().Trim(),
        PotentialRenewalCount = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalCount).Sum(),
        PotentialRenewalSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalSQRT).Sum(),
        desiredCalucation=   (PotentialRenewalCount/PotentialRenewalCount)*100,
        RENEWALCOUNT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALCOUNT).Sum(),
        RENEWALSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALSQRT).Sum()
    };

而我的计算应该是这样的

(PotentialRenewalCount/PotentialRenewalCount)*100

正如我在 select 声明中所描述的那样。

我什至尝试过这个查询,但我得到的结果是 0

 IEnumerable<RenewalModel> result =
            (from r in renewalLists
            group r by r.CityID into grpCity
            select new RenewalModel
            {
                CityID = grpCity.Key,
                City = (from g in grpCity where g.CityID == grpCity.Key select g.City).First().Trim(),
                PotentialRenewalCount = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalCount).Sum(),
                PotentialRenewalSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalSQRT).Sum(),
                RENEWALCOUNT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALCOUNT).Sum(),
                RENEWALSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALSQRT).Sum()
            }).select(r => new RenewalModel
            {
                desiredCalucation = (r.PotentialRenewalCount / r.PotentialRenewalCount) * 100,
                CityID = r.CityID,
                City = r.City,
                PotentialRenewalCount = r.PotentialRenewalCount,
                PotentialRenewalSQRT = r.PotentialRenewalSQRT,
                RENEWALCOUNT = r.RENEWALCOUNT,
                RENEWALSQRT = r.RENEWALSQRT
            });

由于某种原因或另一个 desiredCalucation 变量给我的结果是 0。

感谢任何帮助。 谢谢

为此,使用 LINQ let operator

一般来说,我建议将大的 LINQ 语句拆分成几个小的语句。不然以后调试这个会很痛苦

如果您想从原始查询中提取值,然后填充一个额外的 属性,您可以这样做:

        IEnumerable<RenewalModel> result =
            (from r in renewalLists
            group r by r.CityID into grpCity
            select new RenewalModel
            {
                CityID = grpCity.Key,
                City = (from g in grpCity where g.CityID == grpCity.Key select g.City).First().Trim(),
                PotentialRenewalCount = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalCount).Sum(),
                PotentialRenewalSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalSQRT).Sum(),
                RENEWALCOUNT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALCOUNT).Sum(),
                RENEWALSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALSQRT).Sum()
            }).select(r => new RenewalModel
            {
                desiredCalucation = (r.PotentialRenewalCount / r.PotentialRenewalCount) * 100,
                CityID = r.CityID,
                City = r.City,
                PotentialRenewalCount = r.PotentialRenewalCount,
                PotentialRenewalSQRT = r.PotentialRenewalSQRT,
                RENEWALCOUNT = r.RENEWALCOUNT,
                RENEWALSQRT = r.RENEWALSQRT
            });

虽然您在个人作业中做了很多 "requerying" 相同的记录。您可以通过在 CityID 上使用 "join" 以更简洁的方式完成同样的事情。

请记住,LINQ 还支持子查询:

        IEnumerable<RenewalModel> result =
            (from g in (
                from r in renewalList
                join c in cityList on r.CityID equals c.CityID
                select new RenewalModel
                {
                    CityID = grpCity.Key,
                    City = (from g in grpCity where g.CityID == grpCity.Key select g.City).First().Trim(),
                    PotentialRenewalCount = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalCount).Sum(),
                    PotentialRenewalSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalSQRT).Sum(),
                    RENEWALCOUNT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALCOUNT).Sum(),
                    RENEWALSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALSQRT).Sum()
                })
            group g by g.CityID into grpCity
            select new RenewalModel
            {
                desiredCalucation = (g.PotentialRenewalCount / g.PotentialRenewalCount) * 100,
                CityID = g.CityID,
                City = g.City.Trim(),
                PotentialRenewalCount = g.PotentialRenewalCount.Sum(),
                PotentialRenewalSQRT = g.PotentialRenewalSQRT.Sum(),
                RENEWALCOUNT = g.RENEWALCOUNT.Sum(),
                RENEWALSQRT = g.RENEWALSQRT.Sum()
            });

好吧,假设您想要实际 RenewalModel 的 2 个属性之间的比率,为什么不声明一个只读的 属性,它要么每次都计算,要么在第一次使用时计算?

class RenewalModel
{
    public int desiredCalucation => 
       (PotentialRenewalCount/PotentialRenewalCount)*100;

    // ...
}

顺便说一下,您可能想使用 double 并修改公式以使用适当的变量并使用浮点数进行计算。

您还应该更正变量名中的拼写错误。 Calucation 拼写错误!更糟糕的是,这个名字确实说明了 属性.

的目的

这样做的好处 属性 是它允许代码重用,如果多个查询 return 该信息,它防止从外部更改值并且不会影响 LINQ代码生成。

但是由于原始代码不起作用,而且我们没有任何示例说明它应该做什么,因此很难猜测它应该做什么。

虽然我不明白为什么要将一个数字本身除以乘以 100 - 我相信你正在寻找的东西叫做 let。现在,我还没有对此进行测试,但它的工作方式应该与此类似:

IEnumerable<RenewalModel> result = 
    from r in renewalLists
    group r by r.CityID into grpCity
    let potentialRenewalCount = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalCount).Sum()
    let desiredCalculation = (PotentialRenewalCount/PotentialRenewalCount)*100
    select new RenewalModel
    {
    CityID = grpCity.Key,
    City = (from g in grpCity where g.CityID == grpCity.Key select g.City).First().Trim(),
    PotentialRenewalCount = potentialRenewalCount,
    PotentialRenewalSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.PotentialRenewalSQRT).Sum(),
    DesiredCalucation =   desiredCalculation,
    RENEWALCOUNT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALCOUNT).Sum(),
    RENEWALSQRT = (from g in grpCity where g.CityID == grpCity.Key select g.RENEWALSQRT).Sum()
};

还要考虑 SUM 为 0 的情况,因为这会导致除以零!

当 Linq 将表达式翻译为 SQL 时,它会在执行查询时将值截断为整数,因此当我使用例如:

select new SomeModel{
    Value = 3/7
}

它 returns 0.

但是,当我使用时:

select new SomeModel{
    Value = 3.0 / 7.0
}

returns 正确值 = 0.428...

因此,我认为当您使用 Linq To Entities 使用的表达式时,必须 return 双精度或十进制,您应该将所有值显式写入或强制转换为双精度...

希望对您有所帮助。