In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "how to use C # expression tree Expression to dynamically create expressions". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
In some management backend, it is common to query data with multiple conditions. For example, in the user list, you can query a series of conditions such as "user name", "mobile number", "whether the account is frozen" and so on. The common way to handle this is through a series of if...else.... To splice the conditions. This causes the query interface implementation to stack a pile of code that looks useful but is actually tedious. Therefore, according to the negotiation of the front and back end request message, we can dynamically create the expression tree according to a certain format.
Create a QueryEntity class
QueryEntity is a list of parameters passed to API by the front end. Through this class, the server can know which fields the front end needs to query and what methods (Equals, Contains) to filter.
/ query entity / public class QueryEntity {/ Field name / public string Key {get; set;} / value / public string Value {get; set;} / the operation method corresponds to the OperatorEnum enumeration class / public string Operator {get; set } / logical operator, only AND, OR / public string LogicalOperator {get; set;}} are supported to create OperatorEnum classes
OperatorEnum this is an enumeration class of operation methods that specifies the query methods allowed by API, such as Equals, Contains, and so on.
/ Operation method enumeration / public enum OperatorEnum {/ equals / Equals, / does not equal / NotEqual, / contains / Contains, / what starts / StartsWith / what ends / EndsWith, / greater than / Greater, / greater than or equal to / GreaterEqual, / less than / Less, / less than or equal to / LessEqual,} create the ExpressionExtension class
The ExpressionExtension class realizes the dynamic creation of the expression tree and converts the multi-conditional query passed in the front end into an expression for EFCore query.
/ expression extension / generic public static class ExpressionExtension where T: class, new () {/ expression dynamic splicing / public static Expression ExpressionSplice (List entities) {if (entities.Count)
< 1) { return ex =>True;} var expression_first = CreateExpressionDelegate (entities [0]); foreach (var entity in entities.Skip (1)) {var expression = CreateExpressionDelegate (entity); InvocationExpression invocation = Expression.Invoke (expression_first, expression.Parameters.Cast ()); BinaryExpression binary / / logical operator determines if (entity.LogicalOperator.ToUpper (). Equals ("OR")) {binary = Expression.Or (expression.Body, invocation);} else {binary = Expression.And (expression.Body, invocation) } expression_first = Expression.Lambda (binary, expression.Parameters);} return expression_first;} / create Expression / private static Expression CreateExpressionDelegate (QueryEntity entity) {ParameterExpression param = Expression.Parameter (typeof (T)); Expression key = param; var entityKey = entity.Key.Trim () / contains'.', indicating that the field if (entityKey.Contains ('.')) {var tableNameAndField = entityKey.Split ('.'); key = Expression.Property (key, tableNameAndField [0] .ToString ()); key = Expression.Property (key, tableNameAndField [1] .ToString ()) } else {key = Expression.Property (key, entityKey);} Expression value = Expression.Constant (ParseType (entity)); Expression body = Create_Expression (key, value, entity.Operator); var lambda = Expression.Lambda (body, param); return lambda } / attribute type conversion / query entity / private static object ParseType (QueryEntity entity) {try {PropertyInfo property / contains'.', indicating that the field if (entity.Key.Contains ('.')) {var tableNameAndField = entity.Key.Split ('.'); property = typeof (T) .GetProperty (tableNameAndField [0], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) Property = property.PropertyType.GetProperty (tableNameAndField [1], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);} else {property = typeof (T) .GetProperty (entity.Key, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);} return Convert.ChangeType (entity.Value, property.PropertyType) } catch (Exception) {throw new ArgumentException ("Field type conversion failed: incorrect field name or incorrect value type") }} / create Expression / private static Expression Create_Expression (Expression left, Expression value, string entityOperator) {if (! Enum.TryParse (entityOperator, true, out OperatorEnum operatorEnum)) {throw new ArgumentException ("Operation method does not exist, please check the value of operator") } return operatorEnum switch {OperatorEnum.Equals = > Expression.Equal (left, Expression.Convert (value, left.Type)), OperatorEnum.NotEqual = > Expression.NotEqual (left, Expression.Convert (value, left.Type)), OperatorEnum.Contains = > Expression.Call (left, typeof (string) .GetMethod ("Contains", new Type [] {typeof (string)}), value) OperatorEnum.StartsWith = > Expression.Call (left, typeof (string) .GetMethod ("StartsWith", new Type [] {typeof (string)}), value), OperatorEnum.EndsWith = > Expression.Call (left, typeof (string) .GetMethod ("EndsWith", new Type [] {typeof (string)}), value), OperatorEnum.Greater = > Expression.GreaterThan (left, Expression.Convert (value, left.Type)) OperatorEnum.GreaterEqual = > Expression.GreaterThanOrEqual (left, Expression.Convert (value, left.Type)), OperatorEnum.Less = > Expression.LessThan (left, Expression.Convert (value, left.Type)), OperatorEnum.LessEqual = > Expression.LessThanOrEqual (left, Expression.Convert (value, left.Type)), _ = > Expression.Equal (left, Expression.Convert (value, left.Type),} }} usage example
For example, there are two entity classes, Address is a subclass of User
Public class User {public int Id {get; set;} public string Name {get; set;} = string.Empty; public int Age {get; set;} public DateTime CreateTime {get; set;} public Address Address {get; set;} public class Address {public string Province {get; set;} public string City {get; set;}} single condition query
The name (name) in the query user table contains "chen":
List list = new List {new QueryEntity {Key = "name", Value = "chen", Operator = "Contains"}}; var expression = ExpressionExtension.ExpressionSplice (list); / / expression = Param_0 = > Param_0.Name.Contains ("chen")
Query the age (age) in the user table is greater than or equal to 18:
List list = new List {new QueryEntity {Key = "age", Value = "18", Operator = "GreaterEqual"}}; var expression = ExpressionExtension.ExpressionSplice (list); / / expression = Param_0 = > Param_0.Name.GreaterThanOrEqual (18) Multi-conditional query
The name (name) in the query user table contains "chen" and the age (age) is 18 or greater:
List list = new List {new QueryEntity {Key = "name", Value = "chen", Operator = "Contains"}, new QueryEntity {Key = "age", Value = "18", Operator = "GreaterEqual", / / Note: enter "AND" here to represent the relationship between the two conditions If the query name contains "chen" or is 18 or older, fill in "OR"logicalOperator": "AND"}} Var expression = ExpressionExtension.ExpressionSplice (list); / / expression = Param_0 = > ((Param_0.Status > = Convert (1, Int32)) And Invoke (Param_1 = > Param_1.OpenId.Contains ("9JJdFTVt6oimCgdbW61sk"), Param_0) Multi-table query
The name (name) in the query user table contains "chen" and the address (address) is in Guangdong Province:
List list = new List {new QueryEntity {Key = "name", Value = "chen", Operator = "Contains"}, new QueryEntity {Key = "address.Province", Value = "Guangdong", Operator = "Equals", / / Note: enter "AND" here to represent the relationship between the two conditions If the query name contains "chen" or is 18 or older, fill in "OR"logicalOperator": "AND"}} Var expression = ExpressionExtension.ExpressionSplice (list); / / expression = {Param_0 = > ((Param_0.Address.Province = = Convert ("Guangdong Province", String)) And Invoke (Param_1 = > Param_1.Name.Contains ("chen"), Param_0))} "how to use the C# expression tree Expression to dynamically create expressions" is introduced here, thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.