private static string GetSubConditions <TA, TB>(GenericWhereEntity <TA> mainEntity, GenericWhereEntity <TB> joinEntity, Expression joinExpression, string firstParameter) { if (joinExpression is MemberExpression) { MemberExpression me = (MemberExpression)joinExpression; if (me.Expression.ToString() == firstParameter) { string dbColumnName = EntityMappingTool.GetDbColumnName(mainEntity.EntityType, me.Member.Name); return(string.Format("{0}.[{1}]", mainEntity.TableName, dbColumnName)); } else { string dbColumnName = EntityMappingTool.GetDbColumnName(joinEntity.EntityType, me.Member.Name); return(string.Format("{0}.[{1}]", joinEntity.TableName, dbColumnName)); } } string opr; BinaryExpression be = (BinaryExpression)joinExpression; switch (be.NodeType) { case ExpressionType.Equal: opr = "="; break; case ExpressionType.NotEqual: opr = "<>"; break; case ExpressionType.GreaterThan: opr = ">"; break; case ExpressionType.GreaterThanOrEqual: opr = ">="; break; case ExpressionType.LessThan: opr = "<"; break; case ExpressionType.LessThanOrEqual: opr = "<="; break; default: throw new NotSupportedException("不支持连接条件类型:" + joinExpression.NodeType); } string left = GetSubConditions(mainEntity, joinEntity, be.Left, firstParameter); string right = GetSubConditions(mainEntity, joinEntity, be.Right, firstParameter); string con = string.Format("({0} {1} {2})", left, opr, right); return(con); }
/// <summary> /// 访问操作符 /// </summary> /// <param name="b"></param> /// <returns></returns> protected override Expression VisitBinary(BinaryExpression b) { if (b == null) { return(b); } bool isLeftConstant = (b.Left is ConstantExpression); bool isRightConstant = (b.Right is ConstantExpression); //不支持两端都是静态变量的表达式 if (b.Left is ConstantExpression && b.Right is ConstantExpression) { throw new NotSupportedException("不支持两端都是静态变量的表达式!" + b.ToString()); } //右侧的静态变量访问,如果是null,操作符要进行特殊处理 bool isRightConstantNull = false; if (isRightConstant) { ConstantExpression ce = (ConstantExpression)b.Right; if (ce.Value == null) { isRightConstantNull = true; } } string opr; switch (b.NodeType) { case ExpressionType.Equal: if (isRightConstantNull) { opr = "is"; } else { opr = "="; } break; case ExpressionType.NotEqual: if (isRightConstantNull) { opr = "is not"; } else { opr = "<>"; } break; case ExpressionType.GreaterThan: if (isRightConstantNull) { throw new NotSupportedException("对null值不支持大于的操作"); } opr = ">"; break; case ExpressionType.GreaterThanOrEqual: if (isRightConstantNull) { throw new NotSupportedException("对null值不支持大于等于的操作"); } opr = ">="; break; case ExpressionType.LessThan: if (isRightConstantNull) { throw new NotSupportedException("对null值不支持小于的操作"); } opr = "<"; break; case ExpressionType.LessThanOrEqual: if (isRightConstantNull) { throw new NotSupportedException("对null值不支持小于等于的操作"); } opr = "<="; break; case ExpressionType.AndAlso: if (isRightConstantNull) { throw new NotSupportedException("对null值不支持与的操作"); } opr = "AND"; break; case ExpressionType.OrElse: if (isRightConstantNull) { throw new NotSupportedException("对null值不支持或的操作"); } opr = "OR"; break; case ExpressionType.Add: opr = "+"; break; case ExpressionType.Subtract: opr = "-"; break; case ExpressionType.Multiply: opr = "*"; break; case ExpressionType.Divide: opr = "/"; break; default: throw new NotSupportedException("不支持操作类型:" + b.NodeType); } //如果涉及到访问实体成员,则先检索成员相关信息,再访问子节点。访问完成后,恢复临时成员的信息。 var bkDBColumnName = m_TmpDBColumnName; var bkDBColumnType = m_TmpDBColumnType; var bkUsedParameter = m_TmpUsedParameter; MemberExpression leftMemberExp = null, rightMemberExp = null; bool isLeftMember = false, isRightMember = false; if (b.Left is MemberExpression) { leftMemberExp = b.Left as MemberExpression; } else if (b.Left.NodeType == ExpressionType.Convert) { leftMemberExp = ((UnaryExpression)b.Left).Operand as MemberExpression; } isLeftMember = (leftMemberExp != null); //如果左侧是成员访问,右侧是空值,直接输出语句 if (b.Right is MemberExpression) { rightMemberExp = b.Right as MemberExpression; } else if (b.Right.NodeType == ExpressionType.Convert) { rightMemberExp = ((UnaryExpression)b.Right).Operand as MemberExpression; } isRightMember = (rightMemberExp != null); m_TmpUsedParameter = ((isLeftMember && isRightConstant) || (isRightMember && isLeftConstant)); //左侧是访问成员,肯定要加载 if (isLeftMember) { m_TmpDBColumnName = EntityMappingTool.GetDbColumnName(_TheWhereEntity.EntityType, leftMemberExp.Member.Name); m_TmpDBColumnType = EntityMappingTool.GetDbColumnType(_TheWhereEntity.EntityType, leftMemberExp.Member.Name); //如果是左侧为成员,右侧为null值,需要特殊处理 if (isRightConstantNull) { //1.访问Left this.Visit(b.Left); //2.左条件出栈 string tmpLeftCondition = this.m_conditionParts.Pop(); //3.生成语句并入栈 string tmpCondition = String.Format("({0} {1} {2})", tmpLeftCondition, opr, "null"); this.m_conditionParts.Push(tmpCondition); //4.恢复成员 m_TmpUsedParameter = bkUsedParameter; m_TmpDBColumnType = bkDBColumnType; m_TmpDBColumnName = bkDBColumnName; //5.退出本次执行 return(b); } } else if (isLeftConstant && isRightMember) { m_TmpDBColumnName = EntityMappingTool.GetDbColumnName(_TheWhereEntity.EntityType, rightMemberExp.Member.Name); m_TmpDBColumnType = EntityMappingTool.GetDbColumnType(_TheWhereEntity.EntityType, rightMemberExp.Member.Name); } this.Visit(b.Left); //两侧都是访问成员的话,也加载 if (isLeftMember && isRightMember) { m_TmpDBColumnName = EntityMappingTool.GetDbColumnName(_TheWhereEntity.EntityType, rightMemberExp.Member.Name); m_TmpDBColumnType = EntityMappingTool.GetDbColumnType(_TheWhereEntity.EntityType, rightMemberExp.Member.Name); } this.Visit(b.Right); //恢复成员 m_TmpUsedParameter = bkUsedParameter; m_TmpDBColumnType = bkDBColumnType; m_TmpDBColumnName = bkDBColumnName; string right = this.m_conditionParts.Pop(); string left = this.m_conditionParts.Pop(); //默认的输出格式 string condition = String.Format("({0} {1} {2})", left, opr, right); /* * //输出方式的改变,内部如果存在and将不再重复输出括号,最后在最外层输出输出一个括号 * string condition = null; * switch (b.NodeType) * { * case ExpressionType.AndAlso: * if (NeedQuoteForChildren(b)) * condition = String.Format("({0} {1} {2})", left, opr, right); * else * condition = String.Format("{0} {1} {2}", left, opr, right); * break; * case ExpressionType.OrElse: * if (NeedQuoteForChildren(b)) * condition = String.Format("({0} {1} {2})", left, opr, right); * else * condition = String.Format("{0} {1} {2}", left, opr, right); * break; * default: * condition = String.Format("{0} {1} {2}", left, opr, right); * break; * } * //新的组合方式 */ this.m_conditionParts.Push(condition); return(b); }
/// <summary> /// 访问指定的方法 /// </summary> /// <param name="theEntityType">实体的类型</param> /// <param name="m">访问方法调用相关的表达式</param> /// <param name="tableAlias">表的别名</param> /// <param name="colConditionParts">存储条件节点的栈</param> /// <param name="colParameterNames">存储参数名称的列表</param> /// <param name="colDbTypes">存储数据库字段类型的列表</param> /// <param name="colArguments">存储条件值的列表</param> public static void Visit(Type theEntityType, MethodCallExpression m, string tableAlias, Stack <string> colConditionParts, List <string> colParameterNames, List <DbType> colDbTypes, List <object> colArguments) { var methodName = m.Method.Name; if (m.Object is MemberExpression) { string condition = null; //string memberName = GetMemberName(m.Object as MemberExpression, out theDbType); var memberName = EntityMappingTool.GetDbColumnName(theEntityType, ((MemberExpression)m.Object).Member.Name); var theDbType = EntityMappingTool.GetDbColumnType(theEntityType, ((MemberExpression)m.Object).Member.Name); var parameterName = GetParameterName(colParameterNames, memberName, tableAlias); switch (methodName) { case "Contains": condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add("%" + GetArgumentValue(m.Arguments[0] as ConstantExpression) + "%"); break; case "StartsWith": condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add(GetArgumentValue(m.Arguments[0] as ConstantExpression) + "%"); break; case "EndsWith": condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add("%" + GetArgumentValue(m.Arguments[0] as ConstantExpression)); break; default: throw new EntitySqlException("暂不支持{" + m + "}的调用!"); } } else if (m.Object is ConstantExpression) { string condition = null; var memberName = EntityMappingTool.GetDbColumnName(theEntityType, ((MemberExpression)m.Arguments[0]).Member.Name); var theDbType = EntityMappingTool.GetDbColumnType(theEntityType, ((MemberExpression)m.Arguments[0]).Member.Name); var parameterName = GetParameterName(colParameterNames, memberName, tableAlias); switch (methodName) { case "Contains": condition = string.Format("(CHARINDEX({0},{1}.[{2}])>0)", parameterName, tableAlias, memberName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add(GetArgumentValue(m.Object as ConstantExpression)); break; case "StartsWith": condition = string.Format("(CHARINDEX({0},{1}.[{2}])=1)", parameterName, tableAlias, memberName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add(GetArgumentValue(m.Object as ConstantExpression)); break; default: throw new EntitySqlException("暂不支持{" + m + "}的调用!"); } } else { throw new EntitySqlException("暂不支持{" + m + "}的调用!"); } }