LINQ - Dynamic where-statement

I have the following linq-query:

                settlementConfig = (from c in settlementConfig
                                where (c.ResID == product.ResID || c.ResID == null)
                                   && (c.OrderSign == order.OrderSign || c.OrderSign == null)
                                   && (c.CustodyTypeID == portfolio.CustodyTypeID || c.CustodyTypeID == null)
                                   && (c.StockExchangeID == order.StockExchangeID || c.StockExchangeID == null)
                                   && (c.ProductOnly == productOnly || c.ProductOnly == null)
                                   && (c.DepotCategoryID == depotCategory || c.DepotCategoryID == null)
                               orderby c.ResID descending, c.CustodyTypeID descending, c.StockExchangeID descending, c.DepotCategoryID descending
                                select c).ToList();

settlementConfig is defined this way:  List<SettlementConfigurationStructure> settlementConfig

Now i want to break the code into parts, where some where-statements can be in the query or not (easy said like this:)
string whereQuery  = "";
if (c.ResID != null)
  whereQuery += "(c.ResID == product.ResID || c.ResID == null)";
if (c.OrderSign != null)
   whereQuery += "(c.CustodyTypeID == portfolio.CustodyTypeID || c.CustodyTypeID == null)";

and so on
LVL 53
DhaestAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
DhaestConnect With a Mentor Author Commented:
Found it in the meantime

// dynamic linq-filter
            var predicate = PredicateBuilder.True<SettlementConfigurationStructure>();            

            predicate = predicate.And(c => c.OrderSign == order.OrderSign || c.OrderSign == null);
            predicate = predicate.And(c => c.StockExchangeID == order.StockExchangeID || c.StockExchangeID == null);
            predicate = predicate.And(c => c.ProductOnly == productOnly || c.ProductOnly == null);
            predicate = predicate.And(c => c.DepotCategoryID == depotCategory || c.DepotCategoryID == null);

            if (product.ResID == null)
                predicate = predicate.And(c => c.ResID == YesNoEnum.No || c.ResID == null);
            else
                predicate = predicate.And(c => c.ResID == product.ResID || c.ResID == null);
            
            if (productOnly.Value == YesNoEnum.No)
                predicate = predicate.And(c => c.CustodyTypeID == portfolio.CustodyTypeID || c.CustodyTypeID == null);

            settlementConfig = settlementConfig.Where(predicate.Compile()).ToList();



Extra class:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;

namespace eXimius.Business.OrderGeneration
{

    public static class PredicateBuilder
    {
        public static Expression<Func<T, bool>> True<T>() { return f => true; }
        public static Expression<Func<T, bool>> False<T>() { return f => false; }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                            Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                             Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }
    }
}

Open in new window

0
 
CuteBugCommented:
I would suggest you add a static method(or an extension method) (say IsSelectable) to the class of which "c" is an instance. This will take the "product" as input and within that method you can return true or false based on your conditions.

0
 
DhaestAuthor Commented:
I've found something called PredicateBuilder, but I don't find the correct way to use this predicatefilter into my query


var predicate1 = PredicateBuilder.True<SettlementConfigurationStructure>();            

            predicate1 = predicate1.And(c => c.OrderSign == order.OrderSign || c.OrderSign == null);
            predicate1 = predicate1.And(c => c.StockExchangeID == order.StockExchangeID || c.StockExchangeID == null);
            predicate1 = predicate1.And(c => c.ProductOnly == productOnly || c.ProductOnly == null);
            predicate1 = predicate1.And(c => c.DepotCategoryID == depotCategory || c.DepotCategoryID == null);

            if (product.ResID == null)
                predicate1 = predicate1.And(c => c.ResID == YesNoEnum.No || c.ResID == null);
            else
                predicate1 = predicate1.And(c => c.ResID == product.ResID || c.ResID == null);
            
            if (productOnly.Value == YesNoEnum.No)
                predicate1 = predicate1.And(c => c.CustodyTypeID == portfolio.CustodyTypeID || c.CustodyTypeID == null);

Open in new window

0
 
b_levittCommented:
I know you closed the question, but I think the Linq dynamic query library is much easier:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
0
All Courses

From novice to tech pro — start learning today.