Beispiel #1
0
        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 + "}的调用!");
            }
        }