簡體   English   中英

精簡 linq 查詢

[英]streamline linq query

我嘗試使用 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 查詢,它根據 model 值重復(排序)。 我怎么能縮短這個查詢..如果我可以只使用一個 var object 而不是使用一堆不同的參數..你看到這個代碼是重復的。

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 個額外的 model 參數,並且對於每個參數,都會創建一個新的 var _result 和 _SentSurveys..我只是想簡化此代碼。

我認為首先進行重構可以使編寫這些查詢更容易,這將是有益的。 如果這不是一個選項,您可以使用一些 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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM