Review
The previous article introduced the mode and based on ADO. although the ORM framework is becoming more and more popular, many small and medium enterprises still use ADO.. Net to perform database operations. With the increasing demand of projects and changing business, ADO. net implementation method will make the original simple single-Table operations more complex, especially when the database table changes, as in the ORM framework, by modifying the ing to achieve unified modification, it is very troublesome for programmers to check each piece of related SQL to troubleshoot errors.
No matter what kind of framework, it is not easy to use, so there is no need for design.
Therefore, this article will be implemented based on the ORM framework. The general content is as follows:
- Expression-based implementation
- Use nhib.pdf to query
- Use beego to query
Expression-based implementation
Therefore, in today's C # field, if there is no LINQ style, it will be a bit complicated for the coding staff, so the extension direction must be to support LINQ. In the previous article, we didn't implement the support for LINQ, but left it for everyone to implement. So at the beginning of this article, let's review it first.
Start with a simple call method, for example:
Query. Add <school> (S => S. Name = ""); or query. Add <school> (S => S. age> 20 );
The above two query condition expressions are analyzed and compared with the original criterion, the criterion object can still be generated through the parsing expression. However, since nhib.pdf already supports expressions, therefore, you need to reconstruct the query object mode. First, delete the criterion class and modify the query Code. The Code is as follows:
private List<Expression> m_Criterions = new List<Expression>(); public IEnumerable<Expression> Criterions { get { return m_Expressions; } } public void Add<T>(Expression<Func<T, bool>> exp){ Add(exp as Expression);}public void Add(Expression exp){ if (exp.NodeType == ExpressionType.Lambda) Add((exp as LambdaExpression).Body); else m_Criterions.Add(exp);}
Next, we need to support and or. Because and or involve subqueries, when the queryoperator of the parent query is different from the queryoperator of the subquery, the expression needs to be converted into a subquery, so the code is changed:
public void Add(Expression exp){ if (exp.NodeType == ExpressionType.Lambda) Add((exp as LambdaExpression).Body); else if (exp.NodeType == ExpressionType.OrElse || exp.NodeType == ExpressionType.AndAlso) AddByJunctionExpression(exp); else m_Expressions.Add(exp);}private void AddByJunctionExpression(Expression exp){ var binaryExp = exp as BinaryExpression; if ((Operator == QueryOperator.And && exp.NodeType == ExpressionType.AndAlso) || (Operator == QueryOperator.Or && exp.NodeType == ExpressionType.OrElse)) { Add(binaryExp.Left); Add(binaryExp.Right); } else { Query subQuery = new Query(exp.NodeType == ExpressionType.OrElse ? QueryOperator.Or : QueryOperator.And); subQuery.Add(binaryExp.Left); subQuery.Add(binaryExp.Right); AddSubQuery(subQuery); }}
Now, the expression-based query object transformation is complete. Next we need to convert the query to the corresponding API to query data based on the specific environment of the data layer.
Use nhib.pdf to query
First go to the code, and then analyze the code. The general code is:
public static NHibernate.ICriterion ToNHibernateQuery<T>(Query query){ NHibernate.Junction junction; if (query.Operator == QueryOperator.And) junction = NHibernate.Expression.Conjunction(); else junction = NHibernate.Expression.Disjunction(); if (expressions.Any()) { foreach (var exp in expressions) AppendNHibernateCriterionByExpression(junction, exp); } this.AppendNHibernateCriterionBySubQueries(junction); return junction;}private static void AppendNHibernateCriterionByExpression<T>(NHibernate.Junction junction, Expression exp){ var binaryExp = exp as BinaryExpression; var expression = Expression.Lambda<Func<T, bool>>( exp, GetParameterExpressionBy(binaryExp.Left) ?? GetParameterExpressionBy(binaryExp.Right)); junction.Add(expression);}private static ParameterExpression GetParameterExpressionBy(Expression exp){ if (exp.NodeType != ExpressionType.MemberAccess) return null; var memberExp = exp as MemberExpression; return memberExp.Expression as ParameterExpression;}private static void AppendNHibernateCriterionBySubQueries<T>(NHibernate.Junction junction, IEnumerable<Query> subQueries){ if (!subQueries.Any()) return; foreach (var subQuery in subQueries) { var subCriterion = ToNHibernateQuery<T>(subQuery); junction.Add(subCriterion); }}
Since Nhibernate implements the query object mode internally, you only need to convert the and or conditions into the corresponding Nhibernate class during the conversion process, then, the conditions are added using Nhibernate's support for expressions, and then icriteria is used. list <t> () to obtain the result.
As mentioned in the previous article, the support for the query object mode for external areas is quite troublesome, but it is relatively simple to implement it on the basis of nhib.pdf. I will not introduce it too much here, if you are interested, you need to study nhbernate in depth. Here we recommend that you read Li yongjing's article or buy a basic nhib.pdf book.
Use beego to query
The Go language has been available for some time, and many large companies are using it, so we cannot lag behind. Since the beego framework has recently been used to build a data server, the query object mode is of course necessary. This article also introduces the implementation of the query object mode in the beego framework.
Although most companies still use relational databases, they still cannot stop the pace of nosql, a new database. Recently, nodejs was used for web development, therefore, nosql databases can be used for better database interaction. After all, they can directly use the JSON data structure. However, due to their habits of relational databases, they have to change to relational databases, so we have the go data server mentioned above.
In order to avoid changing the original data query method, the API structure of MongoDB is referenced to implement the query object mode. The Ajax query code is as follows:
$. Ajax ({URL: '/school/find', data: {$ or: {Name: 'zhongyi ', age: {$ GT: 20 }}}});
The above structure is equivalent to select * from school where name = '中 'or age> 20. Based on the previous experience of implementing query object, the conversion of this structure is relatively simple this time. In the go language, the common type is interface {}, which is equivalent to the object of C #. The dictionary also has some differences, but it does not hinder the specific implementation. Here, for simplicity (the structure of Go is too complex), switch is directly used to convert the interface to begoo. The Code is as follows:
func (this *Repository) translateToCriterion(field string, criterion map[string]interface{}, isAnd bool, isNot bool) *orm.Condition { cond := orm.NewCondition() var value interface{} for k, v := range criterion { key := field value = v switch k { case "$take": continue case "$skip": continue case "$sort": continue case "$like": startsWith, endsWith := strings.HasSuffix(v.(string), "%"), strings.HasPrefix(v.(string), "%") chars := []byte(v.(string)) if startsWith && endsWith { key = key + "__icontains"; value = string(chars[1:len(chars)-1]) } else if startsWith { key = key + "__istartswith" value = string(chars[:len(chars)-1]) } else { key = key + "__iendswith" value = string(chars[1:]) } break case "$gt": key = key + "__gt" break case "$lt": key = key + "__lt" break case "$in": key = key + "__in" break case "$not": if reflect.TypeOf(v).Kind() == reflect.Map { value = this.translateToCriterion(field, v.(map[string]interface{}), isAnd, true) } else { isNot = true } break case "$and": value = this.translateToCriterion("", v.(map[string]interface{}), true, isNot) break case "$or": value = this.translateToCriterion("", v.(map[string]interface{}), false, isNot) break default: if v != nil && reflect.TypeOf(v).Kind() == reflect.Map { value = this.translateToCriterion(k, v.(map[string]interface{}), isAnd, isNot) } else if v == nil { key = k + "__isnull" value = true } else { key = k } break } subCond, isCond := value.(*orm.Condition) if isAnd { if isCond { cond = cond.AndCond(subCond) } else if isNot { cond = cond.AndNot(key, value) } else { cond = cond.And(key, value) } } else { if isCond { cond = cond.OrCond(subCond) } else if isNot { cond = cond.OrNot(key, value) } else { cond = cond.Or(key, value) } } } return cond}
In this way, the query object mode under the beego framework is implemented. If you are interested in go, you can also directly use the beego framework to build Web applications, therefore, the front-end can directly use Ajax as previously to implement data access, which is very convenient.
End
Although the query obejct mode can simplify data query, the query interface is fixed due to the use of the query object mode, therefore, you can add a data permission module in the query method to simplify the implementation of data permissions.
So this article is here. If you have any questions or errors, please leave a message for me. Thank you.
Query object -- query object mode (lower)