同一个IQueryable中的两个投影

时间:2014-06-04 23:57:46

标签: linq entity-framework linq-to-entities

是否可以在同一个查询中有两个投影.Select(...)

        int total = ...;

        var sendersInfo = db.Persons
            .Select(p => new
            {
                sentSMS = p.SentSMS.Count(...large expression...),
            })
            // Calculate percentages
            .Select(i => new
            {
                sentSMS = i.sentSMS,
                percentage = i.sentSMS/total * 100
            });

上述情况不起作用,因为显然“i.sentSMS”尚未计算,因此使用0(零)代替结果。

我想避免的是这个(下面),工作,但重复代码“......大表达......”:

        int total = ...;

        var sendersInfo = db.Persons
            .Select(p => new
            {
                sentSMS = p.SentSMS.Count(...large expression...),
                percentage = p.SentSMS.Count(...large expression...) / total * 100
            });

除了我的问题(“有可能......”),有没有最好的方法来实现这一目标?我不喜欢uggly代码。此外,我试图在纯Linq到实体(没有linq到对象)

中实现这一点

1 个答案:

答案 0 :(得分:1)

评论你的评论:

每次都不需要强制浮动 - 只要其中一个操作数是浮点数,另一个操作数被提升,所以结果的类型具有更高的精度(float> int)。

有两个算术运算:

i.sentSMS / total * 100
//       (1)     (2)

分裂,然后相乘。运算符/*都具有相同的优先级(参见例如this),因此从左侧开始计算表达式,首先计算商(因为除数和除数都是{ {1}},结果也是int),然后将结果乘以int(也是100)。

所以,而不是做

int

足以做到:

(float)i.sentSMS / (float)total * 100

甚至更短:

//     ┌─ (float) thanks to casting
//     │           ┌─ (int) -> (float) promotion here, making the result of division a (float) too
//     │           │       ┌─ then 100 gets promoted in the second step the same way
(float)i.sentSMS / total * 100

// ┌─ (float) literal, because 100 is an (int) literal and 100.0 (or 100d) is a (double) literal // │ ┌─ (int) -> (float) promotion // │ │ ┌─ and again 100f * i.sentSMS / total 100f的文字(与float相同,但更整洁):))

在我看来,(float)100看起来更好,但它是100.0的字面值,甚至更高的精确度,因此所有double都会被提升为float,同时生成结果double,因此在将double结果分配给double变量时会收到编译器警告,导致精度下降。