Question

I have a some C# code that is querying a database using nhibernate that looks like this:

      public void Query()
      {

        IEnumerable<Project> list = session.Query<Project>()
            .Where(p => !p.IsDeleted)
            .FetchMany(r => r.UnfilteredProjectApplications)
            .ThenFetch(r => r.Application)
            .ToList()
      }

I now have a number of user driver filters so, based on the parameters passed in, i want to add to the where clause. So something like this:

       public void Query(string name)
      {

         if (!String.IsNullOrEmpty(name)
          {
            IEnumerable<Project> list = session.Query<Project>()
             .Where(p => !p.IsDeleted && p.Name == name)
            .FetchMany(r => r.UnfilteredProjectApplications)
            .ThenFetch(r => r.Application)
            .ToList()
          }
      }
      else
      {
        IEnumerable<Project> list = session.Query<Project>()
            .Where(p => !p.IsDeleted)
            .FetchMany(r => r.UnfilteredProjectApplications)
            .ThenFetch(r => r.Application)
            .ToList()
      }

the user can select one or many filters. As you can imagine, this code above would get ridiculously complicated given the large number of combinations. Is there an elegant way to append a where clause here with additional blocks of logic. Some might be simple such as

         p.Name == name

but others might be more complicated like:

         p.ProjectApplications.Select(r => r.Application).Any(s => applicationIds.Contains(s.Id)))

and as I said, there may be zero or many different filters . .

UPDATE:

i have seen in other cases, people suggesting building up the where clause like

query = query.where (r=>r.name = "XYZ");
query = query.where (r=>r.Age > 10);
query = query.where (r=>r.Gender = "Male");

but that does NOT seem to work with nhibernate so what started was a generic lambda question is now a specific question to nhibernate

Was it helpful?

Solution

You can use the PredicateBuilder<T> to create the expression and apply it on your query, for sample:

public void Query(string name)
{
    Expression<Func<Project, bool>> filter = PredicateBuilder.True<Project>();

    filter = filter.And(p => !p.IsDeleted);

    if (!string.IsNullOrEmpty(name)
        filter = filter.And(p => p.Name == name);

    IEnumerable<Project> list = session.Query<Project>()
                                        .Where(filter)
                                        .FetchMany(r => r.UnfilteredProjectApplications)
                                        .ThenFetch(r => r.Application)
                                        .ToList();
}

With PredicateBuilder you can create the expression you need, adding conditions using And(), Or(), Not() methods.

OTHER TIPS

If you are looking something like this:

public IList<Bestellung> GetAll(Expression<Func<Order, bool>> restriction)
{
    ISession session = SessionService.GetSession();
    IList<Order> bestellungen = session.Query<Order>()
                    .Where(restriction).ToList();
    return bestellungen;
}

Read this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top