开发者

streamline linq query

I have tried using Left outer join using linq. It gives me the same result anytime i change my report parameters.

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();

I have this LINQ query which is repeated (sort of) based on the model value. How would I be able to shorten this query..if I could just use one var object instead of using a bunch for different parameters..as you see this code is repeated.

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();
}

and there are 5 additional model parameters and for each parameters, a new var _result and _SentSurveys are created..i just want to streamline this code.


I think refactoring this first can make writing these queries easier would be beneficial. If this isn't an option, you can use some CompiledQueries to cut down on the repetition of the big queries. But doing so doesn't make it "streamlined" in terms of efficiency, just makes your code slightly cleaner. Additionally, your post-processing in both cases look nearly identical with a lot of unnecessary checks. No need to repeat the common stuff. With some heavy refactoring, you could probably do something like this:

// 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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜