LINQ is it possible to add where clauses dynamically
Asked Answered
H

6

13

I want to search my db with different keys. According to the input, there may be 1 key to 10 keys. Is there a way to add OR/AND clauses to my Linq query dynamically?

 keys[k] // I have my keys in this array 
 var feedList = (from feed in ctx.Feed
                 where feed.content.contains(keys[0]) 
                       && feed.content.contains(keys[1])
                       && ... // continues with the keys.length
                 select new {
                    FeedId = feed.DuyuruId,
                    FeedTitle = feed.FeedTitle,
                    FeedContent = feed.FeedContents,
                    FeedAuthor = user.UserName + " " +User.UserSurname
 }
Hyperextension answered 14/1, 2013 at 14:10 Comment(4)
might want to check out; #848915Wake
I just made up the 10 keys, there should not be any restriction.Hyperextension
link shared by @SomeMiscGuy is what you need. I have created entire linq query and it works like charm. It gels well with existing IEnumerable and IQueryable extensions.Arlana
Dynamic LINQ can be a useful solution, but unnecessary in this example. DLINQ will incur a significant amount of overhead if you use it excessively because it relies on reflection behind the scenes.Womble
W
16

You could try an .All clause to check all the keys:

where keys.All(key => feed.content.contains(key))
Womble answered 14/1, 2013 at 14:17 Comment(0)
Q
7

For AND clauses it is simple:

var feedList = from feed in ctx.Feed;
foreach(var key in keys){
    feedList = feedList.Where(x=> content.contains(key));
}
var resultQuery = feedList.Select(x=> new {....});

For OR you will need to use Expressions or try LinqKit and its predicates :

var predicate = PredicateBuilder.False<TypeOfYourEntity>();
foreach(var key in keys){
    predicate = predicate.Or(x=> content.contains(key));
}
var resultQuery = ctx.Feed.Where(predicate).Select(x=> new {....});
Quickie answered 14/1, 2013 at 14:21 Comment(0)
G
3

You can use the extension methods of LINQ

ctx.Feed.Where(f => {  
//Your logic here
if(something != null){
      return f.Property == something
  } 
}).Select( new { FeedId = feed.DuyuruId,
                    FeedTitle = feed.FeedTitle,
                    FeedContent = feed.FeedContents,
                    FeedAuthor = user.UserName + " " +User.UserSurname })
Galwegian answered 14/1, 2013 at 14:14 Comment(0)
B
2

You can do something like this. Remember it may casue some overhead

 var students = ctx.Students;

 if (!String.IsNullOrWhiteSpace(SearchParams.Name))
      students = from s in students where s.Name.StartsWith(SearchParams.Name)

 if (!String.IsNullOrWhiteSpace(SearchParams.Surname))
      students = from s in students where s.Surname.StartsWith(SearchParams.Surname)
Burka answered 14/1, 2013 at 14:19 Comment(0)
L
2

I wanted to provide an example of how @mellamokb's answer worked for my scenario to possibly help out anyone needing a fairly dynamic linq query.

In my example I have simply made an extension of the datatable class so I can check if a row of data exists as it stands in the database so no SQL primary key exceptions are thrown.

/// <summary>
/// 
/// </summary>
/// <param name="DT"></param>
/// <param name="ColumnNames">Columns to check in affected table.</param>
/// <param name="ItemtoChecks">Values to check in affected column.</param>
/// <returns></returns>
public static bool TableContains(this DataTable DT, string[] ColumnNames, object[] ItemtoChecks)
{
  var result = from row in DT.AsEnumerable()
               where ColumnNames.All(
               r => row.Field<object>(r).ToString() == Convert.ToString(
                 ItemtoChecks[ColumnNames.ToList()
                 .FindIndex(p => p.Equals(r, StringComparison.OrdinalIgnoreCase))]))
               select row;                   
  return (result.Count() > 0);
}

This method allows you to add as many column names as you require to a string[] along with the corresponding values to check in a separate object[]. The query checks against the datatable and if it finds a match the method returns true and if not it returns false.

Leucoplast answered 29/3, 2017 at 18:56 Comment(0)
C
-1

If you need 'OR' or other complexities, you can use Expression class. Check this answer: https://mcmap.net/q/279521/-dynamic-where-clause-in-linq

public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName)
{
    var q = db.ProductDetail.Where(BuildFilter(productGroupName,productTypeName)).Orderby(c=>c.ProductTypeName);
    return q;
}

private static Expression<Func<ProductDetail, bool>> BuildFilter(string productGroupName, string productTypeName)
{
    var p = Expression.Parameter(typeof(ProductDetail));
    return Expression.Lambda<Func<ProductDetail, bool>>(
        Expression.AndAlso(
            Expression.Equal(
                Expression.Property(p, "productGroupName"),
                Expression.Constant(productGroupName)
                ),
            Expression.OrElse(
                Expression.Equal(
                    Expression.Property(p, "productTypeName"),
                    Expression.Constant(productTypeName.ToLower())
                    ),
                Expression.Equal(
                    Expression.Property(p, "productTypeName"),
                    Expression.Constant(productTypeName)
                    )
                )
            ),
            p
        );
}

this would be equivalent to

c.ProductGroupName == productGroupName 
 && (c.ProductTypeName == productTypeName.toLower()
     || c.ProductTypeName == productTypeName
    )
Clifford answered 19/7, 2024 at 18:32 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.