2012-01-06 82 views
1

已经浏览了SO上的许多帖子,并且没有找到任何解决此问题的方法。请注意,此处介绍的所有代码都是简化的,但代表真实代码。我有一个数据表来描述覆盖计划的一些属性。带回最佳匹配查询看起来是这样的:Linq合并结果

select coalesce 
(
(select c.PercentOfCoverageA from CoveragePlans c 
where c.coverage = :COVERAGE 
and c.plancode = :PLANCODE 
and c.statecode = :STATECODE), 

(select c.PercentOfCoverageA from CoveragePlans c 
where c.coverage = :COVERAGE 
and c.plancode = :DEFAULTPLANCODE 
and c.statecode = :STATECODE), 

(select c.PercentOfCoverageA from CoveragePlans c 
where c.coverage = :COVERAGE 
and c.plancode = :DEFAULTPLANCODE 
and c.statecode = :COUNTRYWIDE) 
) as PercentOfCoverageA 
from dual 

这是一张小桌子(几十行)是被击中了很多,很少改变,所以我希望把它变成记忆和使用Linq选择数据来加快速度。

我有这个函数返回的第一场比赛正是我希望它:

decimal GetCoveragePercentage(string coverage, string planCode, string stateCode) 
{ 
    IEnumerable<CoveragePlan> result = Coverages 
     .Where(x => x.Coverage == coverage && x.PlanCode == planCode && x.StateCode == stateCode) 
     .Select(x => x); 

    if (!result.Any()) 
    { 
     result = Coverages 
      .Where(x => x.Coverage == coverage && x.PlanCode == defaultPlanCode && x.StateCode == stateCode) 
      .Select(x => x); 
    } 

    if (!result.Any()) 
    { 
     result = Coverages 
      .Where(x => x.Coverage == coverage && x.PlanCode == defaultPlanCode && x.StateCode == countryWide) 
      .Select(x => x); 
    } 

    return result.First().PercentOfCoverageA; 
} 

我的问题是:有没有更好的方法(更快,代码少,重复更少)来做到这一点的LINQ查询?

更新:我结束了这个功能作为替代:

decimal GetCoveragePercentage(string coverage, string planCode, string stateCode) 
{ 
    return Coverages.Where(x => x.Equals(coverage, planCode, stateCode)) 
     .DefaultIfEmpty(Coverages.Where(x => x.Equals(coverage, defaultPlanCode, stateCode)).FirstOrDefault() 
      ?? Coverages.Where(x => x.Equals(coverage, defaultPlanCode, defaultStateCode)).First()) 
     .First().PercentOfCoverageA; 
} 

的DefaultIfEmpty希望有一个实例,而不是实例的IEnumeration。这导致我在回退子查询中添加First/FirstOrDefault,并且事实证明,如果您给它一个null值,那么DefaultIfEmpty会不喜欢它,所以我使用了null合并操作器来汇总回退级别。

我不知道他们为什么不给你一个DefaultIfEmpty接受一个I​​Enumeration,这纯粹是这样的:

public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> defaultValue) 
{ 
    return (source != null && source.Any()) ? source : defaultValue; 
} 

其实,我想我会使用该扩展方法,并有我的功能是这样的:

decimal GetCoveragePercentage(string coverage, string planCode, string stateCode) 
{ 
    return Coverages.Where(x => x.Equals(coverage, planCode, stateCode)) 
     .DefaultIfEmpty(Coverages.Where(x => x.Equals(coverage, defaultPlanCode, stateCode))) 
     .DefaultIfEmpty(Coverages.Where(x => x.Equals(coverage, defaultPlanCode, defaultStateCode))) 
     .First().PercentOfCoverageA; 
} 

回答

2

我相信.Select(x => x);实际上什么都不做。所以可以删除。您可以使用联合函数来加入您的查询。至于如果没有结果检查,您可以使用此功能DefaultIfEmpty()进行调查。

我也建议resharper有助于优化LINQ的建议。

我也想你应该干校长遵守并没有这行代码:

x.Coverage == coverage && x.PlanCode == defaultPlanCode && x.StateCode == stateCode 

,而不是喜欢的东西取代它:

x.Equals(coverage,defaultPlanCode,stateCode) 

我建议你的LINQ为你的方法会看起来像这样(确保你添加了等效方法优化以及此):

decimal GetCoveragePercentage(string coverage, string planCode, string stateCode) 
{ 
    return Coverages 
     .Where(x => x.Coverage == coverage && x.PlanCode == planCode && x.StateCode == stateCode) 
     .DefaultIfEmpty(Coverages.Where(x => x.Coverage == coverage && x.PlanCode == defaultPlanCode && x.StateCode == stateCode)) 
     .DefaultIfEmpty(Coverages.Where(x => x.Coverage == coverage && x.PlanCode == defaultPlanCode && x.StateCode == countryWide))First().PercentOfCoverageA; 

} 
+0

谢谢!我没有意识到DefaultIfEmpty,这正是我想要照顾的那部分。我讨厌它的重复,它非常湿。我会在早上应用您的建议并回报。 – 2012-01-06 03:57:37