Exemplo n.º 1
0
        /// <summary>
        /// 获取字段或属性成员的 <see cref="ColumnAttribute"/>
        /// </summary>
        /// <param name="member">字段或属性成员</param>
        /// <param name="reflectedType">调用字段或属性成员的实际类型</param>
        /// <returns></returns>
        public static ColumnAttribute GetColumnAttribute(MemberInfo member, Type reflectedType)
        {
            if (member == null)
            {
                return(null);
            }

            if (reflectedType == null)
            {
                reflectedType = member.ReflectedType ?? member.DeclaringType;
            }
            ColumnAttribute column = null;

            if (!TypeUtils.IsAnonymousType(reflectedType) && !TypeUtils.IsPrimitiveType(reflectedType))
            {
                var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(reflectedType);
                var m           = typeRuntime.GetMember(member.Name);
                if (m != null && m is FieldAccessorBase)
                {
                    column = (m as FieldAccessorBase).Column;
                }
            }

            return(column);
        }
Exemplo n.º 2
0
        // 判定 MemberInit 绑定是否声明了一对多关系的导航
        private static bool HasMany(MemberInitExpression node)
        {
            for (int i = 0; i < node.Bindings.Count; i++)
            {
                // primitive 类型
                Type type = (node.Bindings[i].Member as System.Reflection.PropertyInfo).PropertyType;
                if (TypeUtils.IsPrimitiveType(type))
                {
                    continue;
                }

                // complex 类型
                if (TypeUtils.IsCollectionType(type))
                {
                    return(true);
                }

                MemberAssignment memberAssignment = node.Bindings[i] as MemberAssignment;
                if (memberAssignment != null && memberAssignment.Expression.NodeType == ExpressionType.MemberInit)
                {
                    MemberInitExpression initExpression = memberAssignment.Expression as MemberInitExpression;
                    if (HasMany(initExpression))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 3
0
        // 累加表达式中数据库字段的数量
        private static int GetFieldCount(Expression node)
        {
            int num = 0;

            if (node.NodeType == ExpressionType.Lambda)
            {
                node = (node as LambdaExpression).Body;
            }

            switch (node.NodeType)
            {
            case ExpressionType.MemberInit:
                var initExpression = node as MemberInitExpression;
                foreach (var exp in initExpression.NewExpression.Arguments)
                {
                    if (TypeUtils.IsPrimitiveType(exp.Type))
                    {
                        num += 1;
                    }
                    else
                    {
                        num += _countComplex(exp);
                    }
                }
                foreach (MemberAssignment b in initExpression.Bindings)
                {
                    num += _countPrimitive(b.Member);
                }

                break;

            case ExpressionType.MemberAccess:
                var memberExpression = node as MemberExpression;
                num += _countComplex(memberExpression);

                break;

            case ExpressionType.New:
                var newExpression = node as NewExpression;
                //foreach (var exp in newExpression.Arguments) num += _countComplex(exp);
                if (newExpression.Members != null)
                {
                    foreach (var member in newExpression.Members)
                    {
                        num += _countPrimitive(member);
                    }
                }

                break;
            }

            return(num);
        }
Exemplo n.º 4
0
        /// <summary>
        /// 判断字段或属性成员的数据类型是否为 ORM 支持的基元类型
        /// </summary>
        /// <param name="member">字段或属性成员</param>
        /// <returns></returns>
        public static bool IsPrimitive(MemberInfo member)
        {
            Type t = null;

            if (member != null && member.MemberType == MemberTypes.Field)
            {
                t = ((FieldInfo)member).FieldType;
            }
            else if (member != null && member.MemberType == MemberTypes.Property)
            {
                t = ((PropertyInfo)member).PropertyType;
            }

            return(t == null ? false : TypeUtils.IsPrimitiveType(t));
        }
Exemplo n.º 5
0
        // 访问 New 表达式中的参数
        private Expression VisitNewArgumentImpl(Type newType, MemberInfo member, Expression argument)
        {
            // 先添加当前字段的访问痕迹标记
            if (member != null)
            {
                _visitedStack.Add(member, newType);
            }

            if (argument.NodeType == ExpressionType.Parameter)
            {
                //例: new Client(a)
                string alias = _ag.GetTableAlias(argument);
                this.VisitAllMember(argument.Type, alias);
            }
            else if (argument.CanEvaluate())
            {
                //例: DateTime.Now
                _builder.Append(argument.Evaluate().Value, _visitedStack.Current);
                this.AddSelectedColumn(member, newType);
            }
            else if (argument.NodeType == ExpressionType.MemberAccess || argument.NodeType == ExpressionType.Call)
            {
                bool isNavigation = !argument.Type.IsEnum && !TypeUtils.IsPrimitiveType(argument.Type);
                if (isNavigation)
                {
                    this.VisitNavigation(argument as MemberExpression, false);
                }
                else
                {
                    // new Client(a.ClientId)
                    this.Visit(argument);
                    this.AddSelectedColumn(member, newType);
                }
            }
            else
            {
                if (member == null)
                {
                    throw new XFrameworkException("{0} is not support for NewExpression's arguments.");
                }
                base.Visit(argument);
                this.AddSelectedColumn(member, newType);
            }

            return(argument);
        }
Exemplo n.º 6
0
        // 构造由一对多关系产生的嵌套查询
        private static DbQuerySelectTree TryParseOutQuery(DbQuerySelectTree tree)
        {
            if (tree == null || tree.Select == null)
            {
                return(tree);
            }

            Expression          select   = tree.Select.Expressions[0];
            List <DbExpression> includes = tree.Includes;
            Type fromType = tree.From;

            // 解析导航属性 如果有 1:n 的导航属性,那么查询的结果集的主记录将会有重复记录
            // 这时就需要使用嵌套语义,先查主记录,再关联导航记录
            Expression expression       = select;
            var        lambdaExpression = expression as LambdaExpression;

            if (lambdaExpression != null)
            {
                expression = lambdaExpression.Body;
            }
            var initExpression = expression as MemberInitExpression;
            var newExpression  = expression as NewExpression;

            bool hasMany = DbQueryableParser.HasMany(includes);

            if (!hasMany)
            {
                hasMany = initExpression != null && HasMany(initExpression);
            }

            #region 嵌套语义

            if (hasMany)
            {
                newExpression = initExpression != null ? initExpression.NewExpression : newExpression;
                List <MemberBinding> bindings = new List <MemberBinding>();
                if (initExpression != null)
                {
                    bindings = initExpression.Bindings.ToList(a => TypeUtils.IsPrimitiveType((a.Member as System.Reflection.PropertyInfo).PropertyType));
                }

                if (newExpression != null || bindings.Count() > 0)
                {
                    // 简化内层选择器,只选择最小字段,不选择导航字段,导航字段在外层加进去
                    initExpression   = Expression.MemberInit(newExpression, bindings);
                    lambdaExpression = Expression.Lambda(initExpression, lambdaExpression.Parameters);
                    tree.Select      = new DbExpression(DbExpressionType.Select, lambdaExpression);
                }
                tree.Includes = new List <DbExpression>(0);

                var result_Query = new DbQuerySelectTree();
                result_Query.From          = fromType;
                result_Query.Subquery      = tree;
                result_Query.Joins         = null;
                result_Query.OrderBys      = null;
                result_Query.Includes      = includes;
                result_Query.SelectHasMany = true;
                result_Query.Select        = new DbExpression(DbExpressionType.Select, select);

                #region 排序

                if (tree.OrderBys != null && tree.OrderBys.Count > 0)
                {
                    // 是否有分页
                    bool havePaging = (tree.Take > 0 || tree.Skip > 0);
                    if (!havePaging)
                    {
                        // 如果没有分页,则OrderBy需要放在外层
                        result_Query.OrderBys = tree.OrderBys;
                        tree.OrderBys         = new List <DbExpression>(0);
                    }
                    else
                    {
                        // 如果有分页,只有主表/用到的1:1从表放在内层,其它放在外层
                        List <DbExpression> innerOrderBy = null;
                        foreach (var dbExpression in tree.OrderBys)
                        {
                            hasMany = HasMany(dbExpression.Expressions[0] as LambdaExpression);
                            if (!hasMany)
                            {
                                if (innerOrderBy == null)
                                {
                                    innerOrderBy = new List <DbExpression>();
                                }
                                innerOrderBy.Add(dbExpression);
                            }
                        }

                        if (innerOrderBy != null && innerOrderBy.Count > 0)
                        {
                            result_Query.OrderBys = tree.OrderBys;
                            tree.OrderBys         = innerOrderBy;
                        }
                    }
                }

                #endregion

                #region 分组

                if (tree.GroupBy != null)
                {
                    // 查看外层是否需要重新构造选择器。如果有分组并且有聚合函数,则需要重新构造选择器。否则外层解析不了聚合函数
                    // demo => line 1280
                    bool newSelector = bindings.Any(x => ((MemberAssignment)x).Expression.NodeType == ExpressionType.Call) || newExpression.Arguments.Any(x => x.NodeType == ExpressionType.Call);
                    if (newSelector)
                    {
                        ParameterExpression newParameter  = null;
                        List <DbExpression> dbExpressions = null;
                        if (result_Query.Includes != null && result_Query.Includes.Count > 0)
                        {
                            dbExpressions = result_Query.Includes;
                        }
                        else if (result_Query.OrderBys != null && result_Query.OrderBys.Count > 0)
                        {
                            dbExpressions = result_Query.OrderBys;
                        }
                        if (dbExpressions != null && dbExpressions.Count > 0)
                        {
                            newParameter = (dbExpressions[0].Expressions[0] as LambdaExpression).Parameters[0];
                        }

                        // 1对多导航嵌套查询外层的的第一个表别名固定t0,参数名可随意
                        var parameterExpression = newParameter != null ? newParameter : Expression.Parameter(newExpression.Type, "__g");
                        bindings = bindings.ToList(x => (MemberBinding)Expression.Bind(x.Member, Expression.MakeMemberAccess(parameterExpression, x.Member)));
                        List <Expression> arguments = null;
                        if (newExpression.Members != null)
                        {
                            arguments = new List <Expression>(newExpression.Arguments.Count);
                            for (int i = 0; i < newExpression.Arguments.Count; i++)
                            {
                                var member = newExpression.Members[i];
                                var arg    = Expression.MakeMemberAccess(parameterExpression, member);
                                arguments.Add(arg);
                            }
                        }

                        newExpression       = Expression.New(newExpression.Constructor, arguments, newExpression.Members);
                        initExpression      = Expression.MemberInit(newExpression, bindings);
                        lambdaExpression    = Expression.Lambda(initExpression, parameterExpression);
                        result_Query.Select = new DbExpression(DbExpressionType.Select, lambdaExpression);
                    }
                }

                #endregion

                tree = result_Query;
            }

            #endregion

            return(tree);
        }
Exemplo n.º 7
0
        /// <summary>
        /// 访问字段或者属性表达式
        /// </summary>
        /// <param name="node">字段或者成员表达式</param>
        /// <returns></returns>
        protected override Expression VisitMember(MemberExpression node)
        {
            // 1.<>h__TransparentIdentifier3.b.Client.ClientName
            // 2.<>h__TransparentIdentifier3.b.Client.ClientName.Length
            // 3.<>h__TransparentIdentifier3.b.Client.Address.AddressName
            // 4.<>h__TransparentIdentifier3.b.ClientName
            // <>h__TransparentIdentifier2.<>h__TransparentIdentifier3.b.ClientName
            // <>h__TransparentIdentifier2.<>h__TransparentIdentifier3.b.Client.ClientName
            // <>h__TransparentIdentifier2.<>h__TransparentIdentifier3.b.Client.Address.AddressName
            // 5.b.ClientName


            if (node == null)
            {
                return(node);
            }
            // => a.ActiveDate == DateTime.Now  => a.State == (byte)state
            if (node.CanEvaluate())
            {
                return(this.VisitConstant(node.Evaluate()));
            }
            // => DateTime.Now
            if (node.Type == typeof(DateTime) && node.Expression == null)
            {
                return(this.VisitMethodCall(node, MethodCallType.MemberMember));
            }
            // => a.Nullable.Value
            bool isNullable = node.Expression.Type.IsGenericType && node.Member.Name == "Value" && node.Expression.Type.GetGenericTypeDefinition() == typeof(Nullable <>);

            if (isNullable)
            {
                this.Visit(node.Expression);
                return(node);
            }

            // 记录访问成员栈
            _visitedStack.Add(node);

            // => a.Name.Length
            if (TypeUtils.IsPrimitiveType(node.Expression.Type))
            {
                return(this.VisitMethodCall(node, MethodCallType.MemberMember));
            }
            // => <>h__3.b.ClientName
            if (!node.Expression.Visitable())
            {
                _builder.AppendMember(_ag, node);
                return(node);
            }
            // => a.Accounts[0].Markets[0].MarketId
            // => b.Client.Address.AddressName
            Expression objExpression = node.Expression;
            bool       isMethodCall  = objExpression != null && objExpression.NodeType == ExpressionType.Call;

            if (isMethodCall)
            {
                MethodCallExpression methodExpression = objExpression as MethodCallExpression;
                bool isIndex = methodExpression.IsCollectionIndex();
                if (isIndex)
                {
                    objExpression = methodExpression.Object;
                }
            }
            // => b.Client.Address.AddressName
            this.VisitNavMember(objExpression, TypeUtils.GetFieldName(node.Member, node.Expression.Type));

            return(node);
        }
Exemplo n.º 8
0
        /// <summary>
        /// 访问 Lambda 表达式,如 p=>p p=>p.t p=>p.Id
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="node">Lambda 表达式</param>
        /// <returns></returns>
        protected override Expression VisitLambda <T>(Expression <T> node)
        {
            LambdaExpression lambda = node as LambdaExpression;

            if (lambda.Body.NodeType == ExpressionType.Parameter)
            {
                // 例: a=> a
                Type   type  = lambda.Body.Type;
                string alias = _ag.GetTableAlias(lambda);
                this.VisitAllMember(type, alias);
                return(node);
            }
            else if (lambda.Body.CanEvaluate())
            {
                // 例:a=>1
                base.Visit(lambda.Body.Evaluate());
                // 选择字段
                string newName = _selectedColumns.Add(AppConst.CONSTANT_COLUMN_NAME);
                // 添加字段别名
                _builder.AppendAs(newName);
                return(node);
            }
            else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
            {
                // 例: t=> t.a
                // => SELECT a.ClientId
                Type type = lambda.Body.Type;
                if (!TypeUtils.IsPrimitiveType(type))
                {
                    return(this.VisitAllMember(type, _ag.GetTableAlias(lambda.Body), node));
                }
                else
                {
                    var newNode = this.VisitWithoutStack(_ => base.VisitLambda(node));

                    var    memberExpression = lambda.Body as MemberExpression;
                    string memberName       = memberExpression.Member.Name;

                    var srcDbExpressionType = _builder.TranslateContext.CurrentExpressionType;
                    var srcIsOutermost      = _builder.TranslateContext.CurrentIsOutermost;

                    if (!(srcDbExpressionType != null && srcDbExpressionType == DbExpressionType.Select && srcIsOutermost != null && srcIsOutermost.Value))
                    {
                        // 非外层字段,SELECT xx As name 的 name 使用数据库原生字段
                        memberName = TypeUtils.GetFieldName(memberExpression.Member, memberExpression.Expression.Type);
                    }

                    string newName = _selectedColumns.Add(memberName);
                    return(newNode);
                }
            }
            else
            {
                // 例:a => a.DemoCode,选择字段仅选一个基元类型字段。
                // 结果可能返回一个比如字符串类型列表
                var newNode = base.VisitLambda(node);
                if (_selectedColumns.Count == 0)
                {
                    // 选择字段
                    string newName = _selectedColumns.Add(AppConst.CONSTANT_COLUMN_NAME);
                    // 添加字段别名
                    _builder.AppendAs(newName);
                }
                return(newNode);
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// 将 <see cref="IDataRecord"/> 上的当前行反序列化为实体
        /// </summary>
        /// <param name="prevModel">前一行数据</param>
        /// <param name="isThisLine">是否同一行数据</param>
        /// <returns></returns>
        internal object Deserialize(object prevModel, out bool isThisLine)
        {
            isThisLine = false;

            #region 基元类型

            if (_isPrimitive == null)
            {
                _isPrimitive = TypeUtils.IsPrimitiveType(_entityType) || _reader.GetName(0) == AppConst.AUTO_INCREMENT_NAME;
            }
            if (_isPrimitive.Value)
            {
                if (_reader.IsDBNull(0))
                {
                    return(TypeUtils.GetNullValue(_entityType));                     //default(T);
                }
                var obj = _reader.GetValue(0);
                if (obj.GetType() != _entityType)
                {
                    // fix#Nullable<T> issue
                    if (!_entityType.IsGenericType)
                    {
                        obj = Convert.ChangeType(obj, _entityType);
                    }
                    else
                    {
                        Type type2 = _entityType.GetGenericTypeDefinition();
                        if (type2 != typeof(Nullable <>))
                        {
                            throw new NotSupportedException(string.Format("type {0} not suppored.", type2.FullName));
                        }
                        obj = Convert.ChangeType(obj, Nullable.GetUnderlyingType(_entityType));
                    }
                }

                return(obj);
            }

            #endregion

            #region 动态类型

            if (_isDynamic)
            {
                ExpandoObject obj    = new ExpandoObject();
                var           result = ((IDictionary <string, object>)obj);
                for (int i = 0; i < _reader.FieldCount; i++)
                {
                    var value = _reader.GetValue(i);
                    if (value == DBNull.Value)
                    {
                        value = null;
                    }
                    result.Add(_reader.GetName(i), value);
                }
                return((dynamic)obj);
            }

            #endregion

            #region 实体类型

            object model = null;
            if (_map == null || _map.SelectedNavs == null || _map.SelectedNavs.Count == 0)
            {
                // 没有字段映射说明或者没有导航属性
                if (_entityDeserializer == null)
                {
                    _entityDeserializer = _deserializerImpl.GetTypeDeserializer(_entityType, _reader, _map != null ? _map.SelectedColumns : null, 0);
                }
                model = _entityDeserializer(_reader);
            }
            else
            {
                // 第一层
                if (_entityDeserializer == null)
                {
                    _entityDeserializer = _deserializerImpl.GetTypeDeserializer(_entityType, _reader, _map.SelectedColumns, 0, _map.SelectedNavs.MinIndex);
                }
                model = _entityDeserializer(_reader);
                // 若有 1:n 的导航属性,判断当前行数据与上一行数据是否相同
                if (prevModel != null && _map.HasMany)
                {
                    isThisLine = true;
                    foreach (var m in _typeRuntime.KeyMembers)
                    {
                        var value1 = m.Invoke(prevModel);
                        var value2 = m.Invoke(model);
                        isThisLine = isThisLine && value1.Equals(value2);
                        if (!isThisLine)
                        {
                            // Fix issue#换行时清空上一行的导航键缓存
                            _manyNavigationKeys.Clear();
                            break;
                        }
                    }
                }

                // 递归导航属性
                this.Deserialize_Navigation(isThisLine ? prevModel : null, model, string.Empty, isThisLine);
            }

            return(model);

            #endregion
        }