Exemplo n.º 1
0
        // 判定 MemberInit 绑定是否声明了一对多关系的导航
        static bool CheckManyNavigation(LambdaExpression node)
        {
            bool       hasManyNavgation = false;
            Expression myExpression     = node.Body;

            while (myExpression.Acceptable())
            {
                if (myExpression.NodeType == ExpressionType.MemberAccess)
                {
                    myExpression = (myExpression as MemberExpression).Expression;
                }
                else if (myExpression.NodeType == ExpressionType.Call)
                {
                    var  methodExpression = myExpression as MethodCallExpression;
                    bool isGetItem        = methodExpression.IsGetListItem();
                    if (isGetItem)
                    {
                        myExpression = methodExpression.Object;
                    }
                }

                if (TypeUtils.IsCollectionType(myExpression.Type))
                {
                    hasManyNavgation = true;
                    break;
                }
            }

            return(hasManyNavgation);
        }
Exemplo n.º 2
0
        // 判定 MemberInit 绑定是否声明了一对多关系的导航
        static bool CheckManyNavigation(List <DbExpression> include)
        {
            bool hasManyNavgation = false;

            foreach (DbExpression dbExpression in include)
            {
                Expression myExpression = dbExpression.Expressions[0];
                if (myExpression.NodeType == ExpressionType.Lambda)
                {
                    myExpression = (myExpression as LambdaExpression).Body;
                }
                else if (myExpression.NodeType == ExpressionType.Call)
                {
                    myExpression = (myExpression as MethodCallExpression).Object;
                }

                // Include 如果包含List<>泛型导航,则可以判定整个查询包含一对多的导航
                if (TypeUtils.IsCollectionType(myExpression.Type))
                {
                    hasManyNavgation = true;
                    break;
                }
            }

            return(hasManyNavgation);
        }
Exemplo n.º 3
0
        // 判定 MemberInit 绑定是否声明了一对多关系的导航
        static bool IsHasMany(LambdaExpression node)
        {
            bool       hasMany      = false;
            Expression myExpression = node.Body;

            while (myExpression.Visitable())
            {
                if (myExpression.NodeType == ExpressionType.MemberAccess)
                {
                    myExpression = (myExpression as MemberExpression).Expression;
                }
                else if (myExpression.NodeType == ExpressionType.Call)
                {
                    var  methodExpression = myExpression as MethodCallExpression;
                    bool isIndex          = methodExpression.IsCollectionIndex();
                    if (isIndex)
                    {
                        myExpression = methodExpression.Object;
                    }
                }

                // 如果包含List<>泛型导航,则可以判定整个查询包含一对多的导航
                if (TypeUtils.IsCollectionType(myExpression.Type))
                {
                    hasMany = true;
                    break;
                }
            }

            return(hasMany);
        }
Exemplo n.º 4
0
        // 判定 MemberInit 绑定是否声明了一对多关系的导航
        static bool CheckManyNavigation <T>(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;
                    bool hasManyNavgation = CheckManyNavigation <T>(initExpression);
                    if (hasManyNavgation)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 5
0
 /// <summary>
 /// 反序列化实体集合
 /// </summary>
 public T Deserialize <T>()
 {
     if (TypeUtils.IsCollectionType(typeof(T)))
     {
         return(this.DeserializeCollection <T>());
     }
     else
     {
         return(this.DeserializeSingle <T>());
     }
 }
Exemplo n.º 6
0
        // 检查当前成员是否是1:N关系的导航属性
        static bool IsManyNavigation(MemberInfo member)
        {
            if (member == null)
            {
                return(false);
            }

            // 仅支持属性和字段***
            Type type = null;

            if (member.MemberType == MemberTypes.Property)
            {
                type = ((PropertyInfo)member).PropertyType;
            }
            else if (member.MemberType == MemberTypes.Field)
            {
                type = ((FieldInfo)member).FieldType;
            }
            return(type == null ? false : TypeUtils.IsCollectionType(type));
        }
Exemplo n.º 7
0
        // 检查当前成员是否是1:N关系的导航属性
        static bool IsHasMany(MemberInfo info)
        {
            if (info == null)
            {
                return(false);
            }

            // 仅支持属性和字段***
            Type type = null;

            if (info.MemberType == MemberTypes.Property)
            {
                type = ((PropertyInfo)info).PropertyType;
            }
            else if (info.MemberType == MemberTypes.Field)
            {
                type = ((FieldInfo)info).FieldType;
            }
            return(type == null ? false : TypeUtils.IsCollectionType(type));
        }
Exemplo n.º 8
0
        // 反序列化导航属性
        // @prevLine 前一行数据
        // @isLine   是否同一行数据<同一父级>
        void Deserialize_Navigation(object prevModel, object model, string typeName, bool isThisLine)
        {
            // CRM_SaleOrder.Client
            // CRM_SaleOrder.Client.AccountList
            Type            type        = model.GetType();
            TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type);

            if (string.IsNullOrEmpty(typeName))
            {
                typeName = type.Name;
            }

            //foreach (var kvp in _map.Navigations)
            foreach (var navigation in _map.PickNavDescriptors)
            {
                int start = -1;
                int end   = -1;
                if (navigation.FieldCount > 0)
                {
                    start = navigation.StartIndex;
                    end   = navigation.StartIndex + navigation.FieldCount;
                }

                string keyName = typeName + "." + navigation.Name;
                if (keyName != navigation.KeyId)
                {
                    continue;
                }

                var navAccessor = typeRuntime.GetMember(navigation.Name);
                if (navAccessor == null)
                {
                    continue;
                }

                Type navType = navAccessor.DataType;
                Func <IDataRecord, object> deserializer   = null;
                TypeRuntimeInfo            navTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navType);
                object navCollection = null;
                //if (navType.IsGenericType && navTypeRuntime.GenericTypeDefinition == typeof(List<>))
                if (TypeUtils.IsCollectionType(navType))
                {
                    // 1:n关系,导航属性为 List<T>
                    navCollection = navAccessor.Invoke(model);
                    if (navCollection == null)
                    {
                        // new 一个列表类型,如果导航属性定义为接口,则默认使用List<T>来实例化
                        TypeRuntimeInfo navTypeRuntime2 = navType.IsInterface
                            ? TypeRuntimeInfoCache.GetRuntimeInfo(typeof(List <>).MakeGenericType(navTypeRuntime.GenericArguments[0]))
                            : navTypeRuntime;
                        navCollection = navTypeRuntime2.Constructor.Invoke();
                        navAccessor.Invoke(model, navCollection);
                    }
                }

                if (!_deserializers.TryGetValue(keyName, out deserializer))
                {
                    deserializer            = _deserializerImpl.GetTypeDeserializer(navType.IsGenericType ? navTypeRuntime.GenericArguments[0] : navType, _reader, _map.PickColumns, start, end);
                    _deserializers[keyName] = deserializer;
                }

                // 如果整个导航链中某一个导航属性为空,则跳出递归
                object navModel = deserializer(_reader);
                if (navModel != null)
                {
                    if (navCollection == null)
                    {
                        // 非集合型导航属性
                        navAccessor.Invoke(model, navModel);
                        //
                        //
                        //
                    }
                    else
                    {
                        // 集合型导航属性
                        if (prevModel != null && isThisLine)
                        {
                            #region 合并列表

                            // 判断如果属于同一个主表,则合并到上一行的当前明细列表
                            // 例:CRM_SaleOrder.Client.AccountList
                            string[]           keys           = keyName.Split('.');
                            TypeRuntimeInfo    curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();
                            Type               curType        = curTypeRuntime.Type;
                            MemberAccessorBase curAccessor    = null;
                            object             curModel       = prevModel;

                            for (int i = 1; i < keys.Length; i++)
                            {
                                curAccessor = curTypeRuntime.GetMember(keys[i]);
                                curModel    = curAccessor.Invoke(curModel);
                                if (curModel == null)
                                {
                                    continue;
                                }

                                curType        = curModel.GetType();
                                curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(curType);

                                // <<<<<<<<<<< 一对多对多关系 >>>>>>>>>>
                                if (curType.IsGenericType && i != keys.Length - 1)
                                {
                                    curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(curType);
                                    //if (curTypeRuntime.GenericTypeDefinition == typeof(List<>))
                                    if (TypeUtils.IsCollectionType(curType))
                                    {
                                        var m     = curTypeRuntime.GetMember("get_Count");
                                        int count = Convert.ToInt32(m.Invoke(curModel));      // List.Count
                                        if (count > 0)
                                        {
                                            var m2 = curTypeRuntime.GetMember("get_Item");
                                            curModel       = m2.Invoke(curModel, count - 1);  // List[List.Count-1]
                                            curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(curModel.GetType());
                                        }
                                        else
                                        {
                                            // user.Roles.RoleFuncs=>Roles 列表有可能为空
                                            curModel = null;
                                            break;
                                        }
                                    }
                                }
                            }


                            if (curModel != null)
                            {
                                // 如果有两个以上的一对多关系的导航属性,那么在加入列表之前就需要剔除重复的实体


                                bool isAny = false;
                                if (_map.PickNavDescriptors.Count > 1)
                                {
                                    if (_manyNavigationNumber == null)
                                    {
                                        _manyNavigationNumber = _map.PickNavDescriptors.Count(x => IsManyNavigation(x.Member));
                                    }
                                    if (_manyNavigationNumber != null && _manyNavigationNumber.Value > 1)
                                    {
                                        if (!_manyNavigationKeys.ContainsKey(keyName))
                                        {
                                            _manyNavigationKeys[keyName] = new HashSet <string>();
                                        }
                                        curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navModel.GetType());
                                        StringBuilder keyBuilder = new StringBuilder(64);

                                        foreach (var m in curTypeRuntime.KeyMembers)
                                        {
                                            var value = m.Invoke(navModel);
                                            keyBuilder.AppendFormat("{0}={1};", m.Name, (value ?? string.Empty).ToString());
                                        }
                                        string hash = keyBuilder.ToString();
                                        if (_manyNavigationKeys[keyName].Contains(hash))
                                        {
                                            isAny = true;
                                        }
                                        else
                                        {
                                            _manyNavigationKeys[keyName].Add(hash);
                                        }
                                    }
                                }

                                if (!isAny)
                                {
                                    // 如果列表中不存在,则添加到上一行的相同导航列表中去
                                    var myAddMethod = navTypeRuntime.GetMember("Add");
                                    myAddMethod.Invoke(curModel, navModel);
                                }
                            }

                            #endregion
                        }
                        else
                        {
                            // 此时的 navTypeRuntime 是 List<> 类型的运行时
                            // 先添加 List 列表
                            var myAddMethod = navTypeRuntime.GetMember("Add");
                            myAddMethod.Invoke(navCollection, navModel);

                            var           curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navModel.GetType());
                            StringBuilder keyBuilder     = new StringBuilder(64);

                            foreach (var m in curTypeRuntime.KeyMembers)
                            {
                                var value = m.Invoke(navModel);
                                keyBuilder.AppendFormat("{0}={1};", m.Name, (value ?? string.Empty).ToString());
                            }
                            string hash = keyBuilder.ToString();
                            if (!_manyNavigationKeys.ContainsKey(keyName))
                            {
                                _manyNavigationKeys[keyName] = new HashSet <string>();
                            }
                            if (!_manyNavigationKeys[keyName].Contains(hash))
                            {
                                _manyNavigationKeys[keyName].Add(hash);
                            }
                        }
                    }

                    //if (navTypeRuntime.GenericTypeDefinition == typeof(List<>)) navTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navTypeRuntime.GenericArguments[0]);
                    if (TypeUtils.IsCollectionType(navTypeRuntime.Type))
                    {
                        navTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navTypeRuntime.GenericArguments[0]);
                    }
                    if (navTypeRuntime.NavMembers.Count > 0)
                    {
                        Deserialize_Navigation(prevModel, navModel, keyName, isThisLine);
                    }
                }
            }
        }
Exemplo n.º 9
0
        // 构造由一对多关系产生的嵌套查询
        static DbQueryableInfo_Select <TElement> TryBuilOuter <TElement>(DbQueryableInfo_Select <TElement> sQuery)
        {
            if (sQuery == null || sQuery.Select == null)
            {
                return(sQuery);
            }

            Expression          select  = sQuery.Select.Expressions[0];
            List <DbExpression> include = sQuery.Include;
            Type type = sQuery.FromType;

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

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

            foreach (DbExpression d in include)
            {
                Expression exp = d.Expressions[0];
                if (exp.NodeType == ExpressionType.Lambda)
                {
                    exp = (exp as LambdaExpression).Body;
                }
                else if (exp.NodeType == ExpressionType.Call)
                {
                    exp = (exp as MethodCallExpression).Object;
                }

                // Include 如果包含List<>泛型导航,则可以判定整个查询包含一对多的导航
                //if (exp.Type.IsGenericType && exp.Type.GetGenericTypeDefinition() == typeof(List<>)) checkListNavgation = true;
                if (TypeUtils.IsCollectionType(exp.Type))
                {
                    checkListNavgation = true;
                }
                if (checkListNavgation)
                {
                    break;
                }
            }
            if (!checkListNavgation)
            {
                checkListNavgation = initExpression != null && CheckListNavigation <TElement>(initExpression);
            }

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

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

                var outQuery = new DbQueryableInfo_Select <TElement>();
                outQuery.FromType           = type;
                outQuery.SubQueryInfo       = sQuery;
                outQuery.Join               = new List <DbExpression>();
                outQuery.OrderBy            = new List <DbExpression>();
                outQuery.Include            = include;
                outQuery.HaveListNavigation = true;
                outQuery.Select             = new DbExpression(DbExpressionType.Select, select);
                if (sQuery.GroupBy != null)
                {
                    // 查看外层是否需要重新构造选择器。如果有分组并且有聚合函数,则需要重新构造选择器。否则外层解析不了聚合函数
                    // demo=> line 640
                    bool newSelector = bindings.Any(x => ((MemberAssignment)x).Expression.NodeType == ExpressionType.Call) ||
                                       newExpression.Arguments.Any(x => x.NodeType == ExpressionType.Call);
                    if (newSelector)
                    {
                        // 1对多导航嵌套查询外层的的第一个表别名固定t0,参数名可随意
                        ParameterExpression p = Expression.Parameter(newExpression.Type, "__g");
                        bindings = bindings.ToList(x => (MemberBinding)Expression.Bind(x.Member, Expression.MakeMemberAccess(p, 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(p, member);
                                arguments.Add(arg);
                            }
                        }

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

                sQuery = outQuery;
            }
            else if (sQuery.Union.Count > 0 && (sQuery.Take > 0 || sQuery.Skip > 0))
            {
                var outQuery = new DbQueryableInfo_Select <TElement>();
                outQuery.FromType     = type;
                outQuery.Select       = new DbExpression(DbExpressionType.Select, select);
                outQuery.SubQueryInfo = sQuery;
                outQuery.Skip         = sQuery.Skip;
                outQuery.Take         = sQuery.Take;
                outQuery.Join         = new List <DbExpression>();
                outQuery.OrderBy      = new List <DbExpression>();
                outQuery.OrderBy.AddRange(sQuery.OrderBy);

                sQuery.OrderBy = new List <DbExpression>();
                sQuery.Skip    = 0;
                sQuery.Take    = 0;

                sQuery = outQuery;
            }

            return(sQuery);
        }