2012-01-06 83 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