Combine LINQ queries

后端 未结 3 853
情深已故
情深已故 2020-12-22 09:30

I\'m in the process of making a small query thing for a set of results of files.

public class f_results
    {
        public String name { get; set; }
               


        
相关标签:
3条回答
  • 2020-12-22 10:17

    At least I suggest to remove the .ToList() invokes everywhere. As LINQ has a deferred invocation, it will iterate once, even you have:

    var foundfiles = from p in foundfiles where p.size >= sz select p ;
    foundfiles = from p in foundfiles where p.mdate >= test select p
    

    Update (in that case order by should be put after all filters)

    But if you write:

    var foundfiles = (from p in foundfiles where p.size >= sz orderby p.size descending select p).ToList() ;
    foundfiles = (from p in foundfiles where p.mdate >= test select p).ToList();
    

    It will iterate two times - and that might be a serious performance problem.

    But I don't think the code will look much simpler if you make this code as a single query.

    Also, why are you catching all exceptions? You shouldn't do that.

    0 讨论(0)
  • 2020-12-22 10:20

    You could generate your filters beforehand, then apply them all at once - you would only have to iterate your initial enumeration once, something like this (shortened):

    IEnumerable<f_results> foundfiles = new List<f_results>();
    var filters = new List<Func<f_results, bool>>();
    
    if (fsize.Text.Trim() != "")
    {
        long sz = long.Parse(fsize.Text);
        filters.Add(x => x.size >= sz);
    }
    
    if (adate.Text.Trim() != "")
    {
        DateTime test = DateTime.Parse(adate.Text);
        filters.Add(x => x.adate >= test);
    }
    
    foreach (var filter in filters)
    {
        var filterToApply = filter;
        foundfiles = foundfiles.Where(filterToApply);
    }
    finalResults = new BindingList<f_results>(foundfiles);
    

    More importantly don't call ToList() until you have processed all filters, otherwise you keep iterating through your full result list over and over.

    0 讨论(0)
  • 2020-12-22 10:21

    OK - I wanted to semi answer my own question..

    I can combine to a single query, the following works very well.. Ideal? Possibly not!

    Am going to now look at BrokenGlass' suggestion which looks nice and tidy!

       Boolean flag_size = false;
        Boolean flag_adate = false;
        Boolean flag_cdate = false;
        Boolean flag_mdate = false;
        Int64 sz=0;
        DateTime adatetest=DateTime.Now;
        DateTime cdatetest = DateTime.Now;
        DateTime mdatetest = DateTime.Now;
        String mop = mdateop.Text;
        String aop = adateop.Text;
        String cop = cdateop.Text;
    
        if (fsize.Text.Trim() != "")
        {
            try
            {
                sz = Int64.Parse(fsize.Text);
                flag_size = true;
            }
            catch { }
        }
    
        if (adate.Text.Trim() != "")
        {
            try
            {
                adatetest = DateTime.Parse(adate.Text);
                flag_adate = true;
            }
            catch
            { }
        }
        if (cdate.Text.Trim() != "")
        {
            try
            {
                cdatetest = DateTime.Parse(cdate.Text);
                flag_cdate = true;
            }
            catch
            { }
        }
        if (mdate.Text.Trim() != "")
        {
            try
            {
                mdatetest = DateTime.Parse(mdate.Text);
                flag_mdate = true;
            }
            catch
            { }
        }
    
    
        foundfiles = new BindingList<f_results>(totalresults.Find(fname.Text, true));
    
    
                List<f_results> y = (from p in foundfiles.AsParallel() 
                                     where  (!flag_size || (flag_size && p.size >= sz)) &&
                                            (!flag_mdate || (flag_mdate && mop == ">" && p.mdate >= mdatetest) || (flag_mdate && mop == "< " && p.mdate >= mdatetest)) &&
                                            (!flag_adate || (flag_adate && aop == ">" && p.adate >= adatetest) || (flag_adate && aop == "< " && p.adate >= adatetest)) &&
                                            (!flag_cdate || (flag_cdate && cop == ">" && p.cdate >= cdatetest) || (flag_cdate && cop == "< " && p.cdate >= cdatetest))
                                     orderby p.size descending 
                                     select p).ToList();
    
                foundfiles = new BindingList<f_results>(y);
    
    0 讨论(0)
提交回复
热议问题