A simple solution to the dynamic query of Linq (original)

Source: Internet
Author: User

Because the project needs to use Linq to query data, but when performing multi-condition queries, you need to use a lot of if (...! = String. empty. The following two methods are found on the Internet: one is a class written by a foreigner, which is difficult to use; the other is to provide an extension method with a parameter of a type, when this method is called, reflection is used to traverse the attributes of this type, dynamic query parameters are used to compare with the attribute values, and dynamic lambda expressions are constructed. This is also flawed, that is, all attributes of the type need to be traversed, and the construction of lambda expressions can only build = type expressions, there are limitations. So I figured out a way to call it. I only need a line of code, and lambda expressions can be built at will, and now we enter the topic.
Suppose there is a type of Employee, And this type has a set of employeeList, and there is such an extension method Wheres Based on the IEnumerable <T> type (will be introduced later), how to use
One line of code employeeList. wheres (o => o. name = "a" & o. salary> 5000 & o. inDate> = DateTime. now & o. address. contains ("Beijing") implements the following code:

If (! String. IsNullOrEmpty (name ))
{
EmployeeList. Where (o => o. Name = name );
}
If (salary! = Null) the parameter is set to null.
{
EmployeeList. Where (o => o. Name = name );
}
If (inDate! = Null)
{
EmployeeList. Where (o => o. InDate> = inDate );
}
If (! String. IsNullOrEmpty (address ))
{
EmployeeList. Where (o => o. Address. Contains ("Beijing "));
}

Because the Linq Lambda expression will be parsed into a binary tree of an expression during running, this tree only allows the child nodes on the left to exist in the BinaryExpression subnode, while the child nodes on the right do not have the BinaryExpression subnode, however, the MemberExpression subnode (o. name = "a" is a BinaryExpression, o. name and "a" are binaryexpressions ). So employeeList. wheres (o => o. name = "a" & o. salary> 5000 & o. inDate> = DateTime. now & o. address = "Beijing") will be parsed into a binary tree for example:

We only need to find the red node, get the value of the blue node, and then construct a dynamic Lambda expression. The method for obtaining the node is as follows:

/// <Summary> /// parse Expression tree /// </summary> /// <param name = "tree"> </param> /// <returns> </returns> private static Stack <Expression> DivideBinaryExpression (Expression expression) {Stack <Expression> stack = new Stack <Expression> (); if (expression. nodeType! = ExpressionType. andAlso) // to simplify the Call Code, only the root node is allowed as & {stack. push (expression);} else {BinaryExpression tree = expression as BinaryExpression; while (tree! = Null & tree. NodeType = ExpressionType. AndAlso) {stack. Push (tree. Right); if (tree. Left. NodeType! = ExpressionType. AndAlso) {stack. Push (tree. Left);} tree = tree. Left as BinaryExpression; // loop traversal expression} return stack ;}View Code

Then, dynamically construct the Lambda expression based on the obtained node. The method is as follows:

/// <Summary> /// query multiple where clauses /// </summary> /// <typeparam name = "TSource"> Object Type </typeparam> /// <typeparam name = "TResult"> return type of Expression </typeparam> // <param name = "t"> entity set </param> /// <param name = "expression"> expression </param> // <returns> object set </returns> public static IEnumerable <TSource> Wheres <TSource> (this IEnumerable <TSource> t, expression <Func <TSource, bool> expression) {foreach (Expression e in DivideBinaryExpression (expression. Body) {object expressionValue = null; if (e as BinaryExpression )! = Null) {BinaryExpression be = e as BinaryExpression; expressionValue = LambdaExpression. lambda (be. right ). compile (). dynamicInvoke ();} else // to process like o. address. special node {MethodCallExpression mce = e as MethodCallExpression; expressionValue = LambdaExpression. lambda (mce. arguments [0]). compile (). dynamicInvoke ();} if (expressionValue! = Null) {if (! String. isNullOrEmpty (expressionValue. toString () t = t. where (Expression. lambda <Func <TSource, bool> (e, expression. parameters ). compile () ;}} return t ;}View Code

You only need to call a line of code as mentioned above. Although it is not perfect, it can solve at least 90% of the requirements.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.