C# Linq Where Clause as a Variable

C# Linq where clause as a variable

You need to assembly an Expression<Func<T, bool>> and pass it to the Where() extension method:

Expression<Func<T, bool>> whereClause = a => a.zip == 23456;
var x = frSomeList.Where(whereClause);

EDIT: If you're using LINQ to Objects, remove the word Expression to create an ordinary delegate.

How to update a global variable inside `where` clause in LINQ?

Linq queries are lazy, so until you enumerate newList you will not see a change, because your where has not been executed.

var list = new List<string> { "1", "2", "3", "4", "5" };

bool flag = false;
var newList = list.Where(item =>
{
flag = true;
return item == "2";
});

Console.WriteLine(flag); // Flag is still false.

foreach (var item in newList) {
// It doesn't matter what we do here, just that we enumerate the list.
}

Console.Write(flag); // Flag is now true.

The foreach causes the where to execute and sets your flag.

I would really advise against using the where predicate to create a side effect, by the way, but this is how you'd do it.

How to use a string variable in the linq where clause?

Linq doesn't have this functionality by default. You have to use a third party library to do what you want.

Check out this blog by Scott GU on the subject.

http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library

Applying multiple variable where clauses to linq query

The solution in this case which worked for me was to use the Dynamic Expression API to form up a query in the form of a string (akin to an SQL query), and run this directly on the query in the form query.Where("Status=hidden and BatchAgeDays>10");.

Although expression trees would be a usable solution, this form is less verbose and more readable, and overall a great deal less work to implement, and allows multiple clauses to be concatenated into a single call to Where.

https://github.com/kahanu/System.Linq.Dynamic/wiki/Dynamic-Expressions

How do I use a variable with my WHERE clause in my Entity Framework query

When dealing with user select-able search criteria you will need to code for the possible selections. When dealing with building searches I recommend using the Fluent syntax over the Linq QL syntax as it builds an expression that is easy to conditionally modify as you go. From there you can use a Predicate & PredicateBuilder to dynamically compose your WHERE condition.

Jacques solution will work, but the downside of this approach is that you are building a rather large & complex SQL statement which conditionally applies criteria. My preference is to conditionally add the WHERE clauses in the code to ensure the SQL is only as complex as it needs to be.

If you want to do something like a smart search (think Google with one text entry to search across several possible fields)

var whereClause = PredicateBuilder.False<StudentData>();
int id;
DateTime date;
if(int.TryParse(searchTxt, out id))
whereClause = whereClause.Or(x => x.SID == id);
else if(DateTime.TryParse(searchTxt, out date))
whereClause = whereClause.Or(x => x.BirthDate == date);
else
whereClause = whereClause.Or(x => x.FirstName.Contains(searchTxt));

var data = db.StudentData
.Where(whereClause)
.Select(a => new
{
ID = a.SID,
Birthdate = a.BIRTHDTE,
FirstName = a.FNAMES,
PreviousName = a.PREVSURNAME,
EntryQualAwardID = a.EntryQuals.ENTRYQUALAWARDID,
AwardDate = a.EntryQuals.AWARDDATE
}).ToList();

This does some basic evaluations of the search criteria to see if it fits the purpose of the search. I.e. if they can search by name, date, or ID and IDs are numeric, we only search on an ID if the criteria was numeric. If it looked like a date, we search by date, otherwise we search by name. (and potentially other searchable strings)

If they can search for ID, FirstName, and BirthDate and enter one or more of those as separate entry fields (Search criteria page) then based on which entries they fill in you can either pass separate nullable parameters and do the above based on what parameters are passed, or pass a list of search values with something like an Enum for which value was searched for:

I.e. by parameters:

private void ByParameters(int? id = null, DateTime? birthDate = null, string name = null)
{
var whereClause = PredicateBuilder.False<StudentData>();
if(id.HasValue)
whereClause = whereClause.Or(x => x.SID == id.Value);
if(date.HasValue)
{
DateTime dateValue = date.Value.Date;
whereClause = whereClause.Or(x => x.BirthDate == dateValue);
}
if (!string.IsNullOrEmpty(name))
whereClause = whereClause.Or(x => x.FirstName.Contains(name));

// ....
}

If the number of parameters starts to get big, then a custom type can be created to encapsulate the individual null-able values. I.e.:

[Serializable]
public class SearchCriteria
{
public int? Id { get; set; }
public DateTime? BirthDate { get; set; }
public string Name { get; set; }
}
private void ByParameters(SearchCriteria criteria)
{
// ....
}

Or you can compose a more dynamic parameter list object with a criteria type and value but it starts getting more complex than it's probably worth.

Adding additional linq where clauses based on variables

yes its possible just do :

if (courseID > 0)
{
allFeedback = allFeedback.Where(f => f.CourseBooking.CourseID == courseID);
}

if (facilitatorID == 0)
{
allFeedback = allFeedback.Where(f => f.CourseBooking.FacilitatorID == null);
}
else if (facilitatorID > 0)
{
allFeedback = allFeedback.Where(f => f.CourseBooking.FacilitatorID == facilitatorID);
}

You just forgot to assign the result to the variable.

C# Linq extract Where clause

There seams to be a lot of confusion in the answers in regards to IEnumerable and IQueryable in the answers so I will try to help. First of all IEnumerables work with compiled code and IQueryable with expressions. The Expression portion is accessible in any IQueryable with Expression property. It will represent you code with Linq expression tree. You can get the where part of that Expression with a visitor like so.

  static void Main(string[] args)
{
var data = new []
{
new TestClass{ A = "A" },
new TestClass{ A = "" },
new TestClass{ A = "" },
new TestClass{ A = "" },
new TestClass{ A = "" }
};

var queryData = data.AsQueryable();

queryData = queryData.
Where(a => a.A == "A").OrderBy(a => a.A);

Expression<Func<TestClass, bool>> filter = ( new ExpressionGetter<Func<TestClass, bool>>()).GetWhere(queryData);

Console.ReadLine();
}

public class ExpressionGetter<T> : ExpressionVisitor
{
private Expression<T> filter;

protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == "Where")
{
var a = node.Arguments[1] as UnaryExpression;
filter = (Expression<T>)a.Operand;

return node;
}
else
{
return base.VisitMethodCall(node);
}
}

public Expression<T> GetWhere<TElement>(IQueryable<TElement> queryData)
{
filter = null;

this.Visit(queryData.Expression);

return filter;
}
}

BUT the is a simple example that will get you the first where it can find but a Queriable can have multiple wheres transformations and so on. I think the same is not possible with IEnumerable since the delegate references only exists in context of the method you are calling.

linq store select clause as function variable

You can extract the whole common IQueryable<T> to separate property/method. Since LINQ queries are not executed until enumerated (the so called deferred execution), it can be used as base for composing other queries, e.g.

private IQueryable<Tract> Query() => context.Tracts
//.Include(p => p.ContractType)
//.Include(p => p.ContractSubType)
.Select(p => new Tract
{
Id = p.Id,
Acreage = p.Acreage,
Administrative = p.Administrative,
ContractType = new ContractType
{
Id = p.ContractType.Id,
ContractTypeName = p.ContractType.ContractTypeName
},
ContractSubType = new ContractSubType
{
Id = p.ContractSubType.Id,
ContractSubTypeName = p.ContractSubType.ContractSubTypeName
}
});

(Includes are redundant (ignored) for projection (Select) queries)

then

public async Task<IEnumerable<Tract>> GetAllAsync() => 
await Query().OrderByDescending(p => p.Id).ToListAsync();

and

public async Task<Tract> GetByIdAsync(long id) =>
await Query().FirstOrDefaultAsync(p => p.Id == id);


Related Topics



Leave a reply



Submit