Search code examples
c#linqlinqkit

how should I be using PredicateBuilder from LinqKit C#


I have a quite complex Linq query that worked fine in standard Linq. However, I need to change the way the query gets built and depending on user selection include 0:n 'Or' statements in the query.

So to give some context, my original query was built up in the following way:

IQueryable<Booking> booking;
booking = (
    from b in _context.Bookings
        .Include(v => v.Vendor)
        .Include(v => v.PurchaseOrder)
        .ThenInclude(v => v.PurchaseOrderDestinations)
        .Include(l => l.LineLevelBookings)
        .Include(d => d.BookingDangerousGoods)
    select b
);

if (searchModel.BookingStatusId != null)
{
    booking = booking.Where(b => b.BookingStatusId == searchModel.BookingStatusId);
}

and I'd have a number of these and the booking object would gradually reduce as each criteria was met.

I've now got a situation where I need to change this because the query is more complex and 'standard' linq is no longer good enough.

So I'm trying to use PredicateBuilder.

I start with:

var predicate = PredicateBuilder.New<Booking>(true);

and I'm now building the predicate up in a similar way, but this also includes the complex parts:

if (searchModel.PoNumber != null)
{
    predicate = predicate.And(b => b.PoNumber.ToString().StartsWith(searchModel.PoNumber.ToString()));
}

So now I'm at the point where from my origial Line I need to include Vendor, purchaseOrder etc.

And this is my sticking point.

I'm trying :

booking = _context.Bookings
    .Include(v => v.Vendor)
    .Include(v => v.PurchaseOrder)
    .ThenInclude(v => v.PurchaseOrderDestinations)
    .Include(l => l.LineLevelBookings)
    .Include(d => d.BookingDangerousGoods)
    .AsExpandable()
    .Where(t => predicate)
    .ToList();

but predicate redlines with:

Cannot convert Lambda Expression to intended delegate type because some of the return trypes in the block are not implicitly convertible to the delegate return type


Solution

  • booking = _context.Bookings
      .Include(v => v.Vendor)
      .Include(v => v.PurchaseOrder)
      .ThenInclude(v => v.PurchaseOrderDestinations)
      .Include(l => l.LineLevelBookings)
      .Include(d => d.BookingDangerousGoods)
      .Where(predicate) // note that we don't use lambda here
      .ToList();
    

    From my use experience in both classic EF and EF Core, I didn't have to use .AsExpandable() before applying predicate.