【问题标题】:streamline linq query简化 linq 查询
【发布时间】:2011-05-02 21:11:09
【问题描述】:

我尝试使用 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 个额外的模型参数,对于每个参数,都会创建一个新的 var _result 和 _SentSurveys..我只是想简化这段代码。

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    我认为首先进行重构可以使编写这些查询更容易,这将是有益的。如果这不是一个选项,您可以使用一些 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);
        }
    }
    

    【讨论】:

    • 嗨,杰夫,在我尝试您的解决方案之前,您能检查一下我对上面帖子所做的编辑吗?我使用了左连接...每次都得到相同的结果,但这看起来对吗?谢谢!!
    • @bladerunner:你应该问一个单独的问题,因为这是一个不同的问题。
    • 对不起,我在这里添加了一个新帖子stackoverflow.com/questions/5869241/… 将尝试您的解决方案并通知您。谢谢!
    猜你喜欢
    • 2018-02-16
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    相关资源
    最近更新 更多