2011-05-02 144 views
0

我已經嘗試使用左外連接使用LINQ。每當我更改我的報告參數時,它都會給出相同的結果。簡化linq查詢

var _result = (from ls in SessionHandler.CurrentContext.LennoxSurveyResponses 
          from ml 
          in SessionHandler.CurrentContext.MailingListEntries 
           .Where(mle => mle.SurveyCode == ls.SurveyCode).DefaultIfEmpty() 
          from lists 
          in SessionHandler.CurrentContext.MailingLists 
           .Where(m => m.MailingListId == ml.MailingListId).DefaultIfEmpty() 
          from channel 
          in SessionHandler.CurrentContext.Channels 
           .Where(ch => ch.ChannelId == lists.ChannelId).DefaultIfEmpty() 
          from tmChannelGroup 
          in SessionHandler.CurrentContext.ChannelGroups 
           .Where(tcg => tcg.ChannelGroupId == channel.ChannelGroupId).DefaultIfEmpty() 
          from dmChannelGroup 
          in SessionHandler.CurrentContext.ChannelGroups 
           .Where(dcg => dcg.ChannelGroupId == tmChannelGroup.ParentChannelGroupId).DefaultIfEmpty() 
          from amChannelGroup 
          in SessionHandler.CurrentContext.ChannelGroups 
           .Where(acg => acg.ChannelGroupId == dmChannelGroup.ParentChannelGroupId).DefaultIfEmpty() 
          where (model.ChannelId != 0 && channel.ChannelId == model.ChannelId || 
           model.TMId != 0 && channel.ChannelGroupId == model.TMId || 
           model.DistrictId != 0 && dmChannelGroup.ChannelGroupId == model.DistrictId || 
           model.AreaId != 0 && amChannelGroup.ChannelGroupId == model.AreaId || 
           model.AreaId == 0 && amChannelGroup.ChannelGroupId == model.LoggedChannelGroupId || 
           model.DistrictId == 0 && dmChannelGroup.ChannelGroupId == model.LoggedChannelGroupId || 
           model.TMId == 0 && tmChannelGroup.ChannelGroupId == model.LoggedChannelGroupId || 
           model.ChannelId == 0 && tmChannelGroup.ChannelGroupId == model.LoggedChannelGroupId) 
          && (ml.EmailDate != null || ml.LetterDate != null || ml.EmailBounce == null) 
          select ls).ToList(); 

我有這個基於模型值重複(排序)的LINQ查詢。我怎麼能夠縮短這個查詢..如果我可以只使用一個var對象,而不是使用一堆爲不同的參數..當你看到這個代碼重複。

if (model.ChannelId != 0) 
{ 
    var _result = 
     (from ls in SessionHandler.CurrentContext.LennoxSurveyResponses 
     join ml in SessionHandler.CurrentContext.MailingListEntries on ls.SurveyCode equals ml.SurveyCode 
     join m in SessionHandler.CurrentContext.MailingLists on ml.MailingListId equals m.MailingListId 
     join ch in SessionHandler.CurrentContext.Channels on m.ChannelId equals ch.ChannelId 
     where ch.ChannelId == model.ChannelId 
     && ml.EmailBounce == null || ml.EmailBounce.Equals(false) 
     select ls).ToList(); 
    var _SentSurveys = 
     (from ml in SessionHandler.CurrentContext.MailingListEntries 
     join m in SessionHandler.CurrentContext.MailingLists on ml.MailingListId equals m.MailingListId 
     join ch in SessionHandler.CurrentContext.Channels on m.ChannelId equals ch.ChannelId 
     where ch.ChannelId == model.ChannelId 
     && (ml.EmailDate != null || ml.LetterDate != null || ml.EmailBounce == null) 
     select ml).ToList(); 
    model.SentSurveys = _SentSurveys.Count() > 0 ? _SentSurveys.Count() : 0; 
    model.CompletedSurveys = _result.Count() > 0 ? _result.Count() : 0; 
    model.PercentageComplete = model.SentSurveys != 0 ? model.CompletedSurveys/model.SentSurveys : 0; 
    //model.Referring = _result.Average(m => Convert.ToInt32(m.Question1Answer)); 
    model.Referring = Math.Round(_result.Select(m => string.IsNullOrEmpty(m.Question1Answer) ? 0 : Double.Parse(m.Question1Answer)).Average()); 
    model.ServicePerformance = Math.Round(_result.Select(m => string.IsNullOrEmpty(m.Question2Answer) ? 0 : Double.Parse(m.Question2Answer)).Average()); 
    model.InstallPerformance = Math.Round(_result.Select(m => string.IsNullOrEmpty(m.Question3Answer) ? 0 : Double.Parse(m.Question3Answer)).Average()); 
    model.ReferringLennox = Math.Round(_result.Select(m => string.IsNullOrEmpty(m.Question4Answer) ? 0 : Double.Parse(m.Question4Answer)).Average()); 
} 
else if (model.TMId != 0) 
{ 
    var _result = 
     (from ls in SessionHandler.CurrentContext.LennoxSurveyResponses 
     join ml in SessionHandler.CurrentContext.MailingListEntries on ls.SurveyCode equals ml.SurveyCode 
     join m in SessionHandler.CurrentContext.MailingLists on ml.MailingListId equals m.MailingListId 
     join ch in SessionHandler.CurrentContext.Channels on m.ChannelId equals ch.ChannelId 
     where ch.ChannelGroupId == model.TMId 
     select ls).ToList(); 
    var _SentSurveys = 
     (from ml in SessionHandler.CurrentContext.MailingListEntries 
     join m in SessionHandler.CurrentContext.MailingLists on ml.MailingListId equals m.MailingListId 
     join ch in SessionHandler.CurrentContext.Channels on m.ChannelId equals ch.ChannelId 
     where ch.ChannelGroupId == model.TMId 
     && (ml.EmailDate != null || ml.LetterDate != null || ml.EmailBounce == null) 
     select ml).ToList(); 
    model.SentSurveys = _SentSurveys.Count() > 0 ? _SentSurveys.Count() : 0; 
    model.CompletedSurveys = _result.Count() > 0 ? _result.Count() : 0; 
    model.PercentageComplete = model.SentSurveys != 0 ? model.CompletedSurveys/model.SentSurveys : 0; 

    model.Referring = _result.Select(m => string.IsNullOrEmpty(m.Question1Answer) ? 0 : Double.Parse(m.Question1Answer)).Average(); 
    model.ServicePerformance = _result.Select(m => string.IsNullOrEmpty(m.Question2Answer) ? 0 : Double.Parse(m.Question2Answer)).Average(); 
    model.InstallPerformance = _result.Select(m => string.IsNullOrEmpty(m.Question3Answer) ? 0 : Double.Parse(m.Question3Answer)).Average(); 
    model.ReferringLennox = _result.Select(m => string.IsNullOrEmpty(m.Question4Answer) ? 0 : Double.Parse(m.Question4Answer)).Average(); 
} 

,並有5個額外的模型參數和每個參數,一個新的變種_result和_SentSurveys是created..i只是想簡化此代碼。

回答

0

我認爲這首先重構可以使寫這些查詢更容易將是有益的。如果這不是一個選項,您可以使用一些CompiledQueries來減少重複查詢。但是這樣做並不能使它在效率方面「精簡」,只是讓你的代碼更加清晰。此外,在這兩種情況下,您的後期處理看起來幾乎與大量不必要的檢查相同。無需重複常見的東西。有一些重構,你可以做這樣的事情:

// need to set up the compiled queries first 
static readonly Func<MyDataContextType, 
        MyModelType, 
        Func<MyDataContextType, MailingListEntry, MailingList, Channel, MyModelType, bool>, 
        IQueryable<LennoxSurveyResponse>> 
    GetResult = CompiledQuery.Compile(
     (MyDataContextType ctx, MyModelType mod, 
     Func<MyDataContextType, MailingListEntry, MailingList, Channel, MyModelType, bool> pred) => 
      from lsr in ctx.LennoxSurveyResponses 
      join mle in ctx.MailingListEntries on lsr.SurveyCode equals mle.SurveyCode 
      join ml in ctx.MailingLists on mle.MailingListId equals ml.MailingListId 
      join ch in ctx.Channels on ml.ChannelId equals ch.ChannelId 
      where pred(ctx, mod, mle, ml, ch) 
      select lsr); 

static readonly Func<MyDataContextType, MyModelType, IQueryable<MailingListEntry>> 
    GetSentSurveys = CompiledQuery.Compile(
     (MyDataContextType ctx, MyModelType mod) => 
      from mle in ctx.MailingListEntries 
      join ml in ctx.MailingLists on mle.MailingListId equals ml.MailingListId 
      join ch in ctx.Channels on ml.ChannelId equals ch.ChannelId 
      where ch.ChannelId == mod.ChannelId 
       && (mle.EmailDate != null || mle.LetterDate != null || mle.EmailBounce == null) 
      select mle); 

static readonly Func<MyDataContextType, MyModelType, MailingListEntry, MailingList, Channel, bool> 
    ChannelPredicate = CompiledQuery.Compile(
     (MyDataContextType ctx, MyModelType mod, 
     MailingListEntry mle, MailingList ml, Channel ch) => 
      ch.ChannelId == mod.ChannelId && ml.EmailBounce == null || !ml.EmailBounce.Value); 

static readonly Func<MyDataContextType, MyModelType, MailingListEntry, MailingList, Channel, bool> 
    TMPredicate = CompiledQuery.Compile(
     (MyDataContextType ctx, MyModelType mod, 
     MailingListEntry mle, MailingList ml, Channel ch) => 
      ch.ChannelGroupId == mod.TMId); 

static void UpdateModel(MyModelType model) 
{ 
    if (model.ChannelId == 0 && model.TMId == 0) return; 

    var currentContext = SessionHandler.CurrentContext; 
    var predicate = (model.ChannelId != 0) ? ChannelPredicate : TMPredicate; 
    var results = GetResults(currentContext, model, predicate).ToList(); 
    var sentSurveys = GetSentSurveys(currentContext, model).ToList(); 

    model.SentSurveys = sentSurveys.Count(); 
    model.CompletedSurveys = results.Count(); 
    model.PercentageComplete = model.SentSurveys != 0 ? model.CompletedSurveys/model.SentSurveys : 0; 

    model.Referring = _result.Average(m => string.IsNullOrEmpty(m.Question1Answer) ? 0 : Double.Parse(m.Question1Answer)); 
    model.ServicePerformance = _result.Average(m => string.IsNullOrEmpty(m.Question2Answer) ? 0 : Double.Parse(m.Question2Answer)); 
    model.InstallPerformance = _result.Average(m => string.IsNullOrEmpty(m.Question3Answer) ? 0 : Double.Parse(m.Question3Answer)); 
    model.ReferringLennox = _result.Average(m => string.IsNullOrEmpty(m.Question4Answer) ? 0 : Double.Parse(m.Question4Answer)); 

    if (model.ChannelId != 0) 
    { 
     // should be rounded 
     model.Referring = Math.Round(model.Referring); 
     model.ServicePerformance = Math.Round(model.ServicePerformance); 
     model.InstallPerformance = Math.Round(model.InstallPerformance); 
     model.ReferringLennox = Math.Round(model.ReferringLennox); 
    } 
} 
+0

嗨,傑夫,在我嘗試你的解決方案之前,你能檢查我對我的帖子上面做的編輯嗎?我用左連接...每次都得到相同的結果,但是這樣看起來是正確的嗎?謝謝!! – bladerunner 2011-05-02 23:14:06

+0

@bladerunner:由於這是一個不同的問題,您應該另外提出一個問題。 – 2011-05-02 23:32:25

+0

對不起,我在這裏添加了一個新帖子http://stackoverflow.com/questions/5869241/left-join-using-linq-query..i會給你的解決方案一個嘗試,並會讓你知道。謝謝! – bladerunner 2011-05-03 13:00:46