3 Replies - 396 Views - Last Post: 07 February 2020 - 11:56 AM Rate Topic: -----

#1 andrewsw   User is offline

  • never lube your breaks
  • member icon

Reputation: 6833
  • View blog
  • Posts: 28,345
  • Joined: 12-December 12

inject predicate into LINQ expression

Posted 04 February 2020 - 02:26 AM

I have this method (used in an ASP.NET MVC application) to return a list of job numbers, and I have hard-coded the where clause:

        public DataContextResult<List<Combo>> GetExistingJobList()
        {
            try
            {
                var query = (from pmJobs in Context.PMJobs.AsNoTracking()
                             where pmJobs.Cancelled == false && pmJobs.CallLoggedDate >= DateTime.Today.AddMonths(-12)
                             orderby pmJobs.JobNumber
                             select new Combo
                             {
                                 UID = pmJobs.UID,
                                 Name = pmJobs.JobNumber
                             }).ToList();

                return new DataContextResult<List<Combo>>(query);
            }
            catch (Exception e)
            {
                return new DataContextResult<List<Combo>>(e);
            }
        }

[It returns List<Combo> as the items will generally then be the source of a select picker.]

[A glitch I have currently with the above method is that I also need to use AsEnumerable() otherwise the method AddMonths is not recognised by LINQ.]

How could I set about, instead, passing the predicate (where clause) into the method? I think perhaps I would create something like Func<bool>, and perhaps use the let keyword in the LINQ expression to "inject" the predicate?

Is this achievable without the use of an add-in such as a PredicateBuilder?

Is This A Good Question/Topic? 0
  • +

Replies To: inject predicate into LINQ expression

#2 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7506
  • View blog
  • Posts: 15,556
  • Joined: 16-October 07

Re: inject predicate into LINQ expression

Posted 04 February 2020 - 11:32 AM

Forgive me, but that linq syntax makes me twitch.

Rather, I'd write it like so:
public IEnumerable<Combo> GetExistingJobList() =>
    Context.PMJobs.AsNoTracking()
    .Where(x => !x.Cancelled == false && x.CallLoggedDate >= DateTime.Today.AddMonths(-12))
    .OrderBy(x => x.JobNumber)
    .Select(x => new Combo() { UID = x.UID, Name = x.JobNumber });



Given this, you can reasonably rewrite the above as:
public IEnumerable<Combo> GetJobList(Func<PMJob, bool> pred) =>
    Context.PMJobs.AsNoTracking()
    .Where(pred)
    .OrderBy(x => x.JobNumber)
    .Select(x => new Combo() { UID = x.UID, Name = x.JobNumber });

public IEnumerable<Combo> GetExistingJobList() =>
    GetJobList(x => !x.Cancelled == false && x.CallLoggedDate >= DateTime.Today.AddMonths(-12));



There is a nasty caveat here. If you're working with SQL to Linq then plucking a predicate expression from out of the stream will usually break the SQL expression builder. The code will still run, but optimizations can be lost. If you're just working on an IEnumerable, rather than an IQueryable, then you have the above flexibility without impact.
Was This Post Helpful? 1
  • +
  • -

#3 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7244
  • View blog
  • Posts: 24,556
  • Joined: 05-May 12

Re: inject predicate into LINQ expression

Posted 04 February 2020 - 12:26 PM

Since the predicate is being extracted out anyway, some the techniques here may work with LINQ (to SQL): Calling functions in LINQ queries
Was This Post Helpful? 2
  • +
  • -

#4 TechnoBear   User is offline

  • Lady A
  • member icon

Reputation: 492
  • View blog
  • Posts: 1,461
  • Joined: 02-November 11

Re: inject predicate into LINQ expression

Posted 07 February 2020 - 11:56 AM

You can either use SqlFunctions:

SqlFunctions.DateAdd("month",1,DateTime.Today)


Or you can set the date variable outside the where clause:

var testdate = DateTime.Today.AddMonths(-12);
var query = (from pmJobs in Context.PMJobs.AsNoTracking()
                     where pmJobs.Cancelled == false && pmJobs.CallLoggedDate >= testdate
                     orderby pmJobs.JobNumber
                     select new Combo
                     {
                         UID = pmJobs.UID,
                         Name = pmJobs.JobNumber
                     }).ToList();

Was This Post Helpful? 1
  • +
  • -

Page 1 of 1