已在SO上查看了很多帖子,但没有找到任何解决此问题的帖子。请注意,此处显示的所有代码均已简化,但代表了真实代码。我有一个数据表,描述了覆盖计划的一些属性。恢复最佳匹配的查询看起来像这样:
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合并操作符来汇总后备级别。
我不确定他们为什么不给你一个接受IEnumeration的DefaultIfEmpty,它就是这样:
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;
}
答案 0 :(得分:2)
我相信.Select(x => x);
实际上什么也没做。这样就可以删除了。您可以使用union函数加入查询。至于如果没有结果检查,您可以使用此函数DefaultIfEmpty()
进行调查。
我还建议resharper对优化LINQ的建议有所帮助。
我还认为你应该遵守DRY原则并且没有这行代码:
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;
}