丑陋的LINQ声明,更好的方法?

时间:2012-01-18 11:07:59

标签: c# .net linq linq-to-entities

我有一个LINQ语句,它将多列的值相加,每个列以'HH'开头,尽管还有其他列可用:

//TODO Clean up this mess
var query1 = (from e in Data
                where e.SD == date
                select e).Select(x =>   x.HH01 + x.HH16 + x.HH17 + x.HH18 + x.HH19 + x.HH20 + x.HH21 + x.HH22 + x.HH23 +
                                        x.HH24 + x.HH25 + x.HH26 + x.HH27 + x.HH28 + x.HH29 + x.HH30 + x.HH31 + x.HH32 + 
                                        x.HH33 + x.HH34 + x.HH35 + x.HH36 + x.HH37 + x.HH38 + x.HH39 + x.HH40 + x.HH41 +
                                        x.HH42 + x.HH43 + x.HH44 +x.HH45 + x.HH46 + x.HH47 + x.HH48 + x.HH49.GetValueOrDefault()+
                                        x.HH50.GetValueOrDefault());

return query1.FirstOrDefault();

有没有办法整理一下?我必须做很多变化(用不同的方法),所以如果可能的话,它会清除很多“绒毛”。

另外,我想在每一列上调用.GetValueOrDefault(),但目前我已经将其删除了,因为除了最后两列之外的其他内容。

建议非常感谢!

3 个答案:

答案 0 :(得分:2)

我想你可以使用思考:

double GetHHSum<T>(T x) where T : class
{
   double result = 0;

   var properties = typeof(T).GetProperties();
   foreach (var property in properties)
   {
       if (property.Name.StartsWith("HH"))
          sum += Convert.ToSingle(property.GetValue(x)).GetValueOrDefault();
   }

   return result;
}

然后像这样使用它:

return (from e in Data
        where e.SD == date
        select e).ToList().Select(x => GetHHSum(x)).FirstOrDefault();

代码未经过测试

答案 1 :(得分:2)

我可能错了,因为我不知道你的数据,但在我看来,它们并没有完全正常化(重复属性)。 您可以考虑转到第3个表单 - 从而创建一个/一个单独的表,它将按行包含一个值 - 然后在您的linq查询中连接您的2个表。

链接查询看起来会好得多,以后您可以在不更改查询的情况下更改HH字段。

答案 2 :(得分:1)

一个建议是重构上面的代码以使用LINQ方法链和lambdas(个人偏好),然后将select lambda提取到一个单独的方法中。例如:

// Note select e and .Select(x => x..) is redundant. Only need one
var query1 = Data.Where(e => e.SD == date).Select(SumOfHValues);
return query1.FirstOrDefault();

// Note types are unclear in your question so I've put dummy placeholders
private static QueryResultType SumOfHValues(YourInputClassType x)
{
    // Nothing wrong with this syntactically, it will be faster than a 
    // reflection solution
    // 
    // Algorithmic code tends to have this sort of look & feel. 
    // You could make it more readable
    // by commenting exactly what the summation is doing and 
    // with a mathematical notation or link to documentation / web source
    return x.HH01 + x.HH16 + x.HH17 + x.HH18 + 
           x.HH19 + x.HH20 + x.HH21 + x.HH22 + 
           x.HH23 + x.HH24 + x.HH25 + x.HH26 + 
           x.HH27 + x.HH28 + x.HH29 + x.HH30 + 
           x.HH31 + x.HH32 + x.HH33 + x.HH34 + 
           x.HH35 + x.HH36 + x.HH37 + x.HH38 + 
           x.HH39 + x.HH40 + x.HH41 + x.HH42 + 
           x.HH43 + x.HH44 + x.HH45 + x.HH46 + 
           x.HH47 + x.HH48 + 
           x.HH49.GetValueOrDefault() +
           x.HH50.GetValueOrDefault()
}

此外,如果您想在每个HHxx属性上调用GetValueOrDefault(),您可以将其包装在另一个辅助函数中。这真的归结为代码偏好。你喜欢哪个?看到.GetValueOrDefault()在每个属性访问结束或周围的函数?例如

return x.HH01 + x.HH16 + x.HH17 + x.HH18

变为

return Get(x.HH01) + Get(x.HH16) + Get(x.HH17) + Get(x.HH18) ... 

private static HClassType Get(HClassType input)
{ 
    return input.GetValueOrDefault();
} 

就个人而言,我只需要在列中订购我的HHxx + HHyy代码并在每个代码上调用.GetValueOrDefault()。如果它至少只写了一次辅助方法一次,即使它是冗长的。

致以最诚挚的问候,