Search code examples
c#linqwhere-clauseconditional-statementsdynamic-linq

Dynamic Or Clause Linq


Today we currently have a statement like this:

var Query = (from dp in db.Patients
            select dp);

var UserID = User.Identity.GetUserId();

if (User.IsInRole("Administrator"))
{
    Query = Query.Where(x => x.AdministratorID == UserID);
}
if (User.IsInRole("Counselor"))
{
    Query = Query.Where(x => x.CounselorID == UserID);
}
if (User.IsInRole("Physician"))
{
    Query = Query.Where(x => x.PhysicianID == UserID);
}

The problem is we have Users that can have multiple roles. If a User is both an Counselor and Physician we want the system to pull back all patients where CounselorID == UserID or PhysicianID == UserID.

How can this be accomplished dynamically if we don't know what role a user will have when the page is loaded?

The current .Where clause just uses an AND statement we need an OR statment.

Ideally there would be a solution like this:

if (User.IsInRole("Administrator"))
{
     Query = Query.Where(x => x.AdministratorID == UserID);
}
if (User.IsInRole("Counselor"))
{
     Query = Query.WhereOr(x => x.CounselorID == UserID);
}
if (User.IsInRole("Physician"))
{
     Query = Query.WhereOr(x => x.PhysicianID == UserID);
}

Solution

  • You can build a predicate incrementally.

    Func<Pantient, bool> predicate = p => false;
    
    if (User.IsInRole("Administrator"))
    {
        var oldPredicate = predicate;
        predicate = p => oldPredicate(p) || p.AdministratorID == UserID;
    }
    
    if (User.IsInRole("Counselor"))
    {
        var oldPredicate = predicate;
        predicate = p => oldPredicate(p) || p.CounselorID == UserID;
    }
    
    
    var query = db.Patients.Where(predicate);