Exemplo n.º 1
0
        // 获取 LEFT JOIN / INNER JOIN 子句关联表的的别名
        private void GetLfInJoinAlias(DbExpression exp, TableAliasCache aliases)
        {
            Type   type = exp.Expressions[0].Type.GetGenericArguments()[0];
            string name = TypeRuntimeInfoCache.GetRuntimeInfo(type).TableName;

            // on a.Name equals b.Name 或 on new{ Name = a.Name,Id=a.Id } equals new { Name = b.Name,Id=b.Id }
            LambdaExpression left  = exp.Expressions[1] as LambdaExpression;
            LambdaExpression right = exp.Expressions[2] as LambdaExpression;
            NewExpression    body1 = left.Body as NewExpression;

            if (body1 == null)
            {
                aliases.GetTableAlias(exp.Expressions[1]);
                string alias = aliases.GetTableAlias(exp.Expressions[2]);

                // 记录显示指定的LEFT JOIN 表别名
                aliases.AddOrUpdateJoinTableAlias(name, alias);
            }
            else
            {
                NewExpression body2 = right.Body as NewExpression;
                for (int index = 0; index < body1.Arguments.Count; ++index)
                {
                    aliases.GetTableAlias(body1.Arguments[index]);
                    string alias = aliases.GetTableAlias(body2.Arguments[index]);

                    // 记录显示指定的LEFT JOIN 表别名
                    aliases.AddOrUpdateJoinTableAlias(name, alias);
                }
            }
        }
        // 选择所有的字段
        private Expression VisitAllMember(Type type, string alias, Expression node = null)
        {
            TypeRuntimeInfo runtimeInfo = TypeRuntimeInfoCache.GetRuntimeInfo(type);
            Dictionary <string, Inte.XFramework.Reflection.MemberAccessWrapper> wrappers = runtimeInfo.Wrappers;

            //Fixed issue# 匿名类的字段不能Set
            //runtimeInfo.IsAnonymousType
            //? type.GetProperties().ToDictionary(p => p.Name, p => new Inte.XFramework.Reflection.MemberAccessWrapper(p))
            //: runtimeInfo.Wrappers;

            foreach (var w in wrappers)
            {
                var wrapper = w.Value;// as Inte.XFramework.Reflection.MemberAccessWrapper;
                var mapper  = wrapper as MemberAccessWrapper;
                if (mapper != null && mapper.Column != null && mapper.Column.NoMapped)
                {
                    continue;
                }
                if (mapper != null && mapper.ForeignKey != null)
                {
                    continue;                                              // 不加载导航属性
                }
                _builder.AppendMember(alias, wrapper.Member.Name);

                // 选择字段
                string newName = ColumnExpressionVisitor.AddColumn(_columns, wrapper.Member.Name);
                // 添加字段别名
                _builder.AppendAs(newName);
                _builder.Append(",");
                _builder.AppendNewLine();
            }

            return(node);
        }
Exemplo n.º 3
0
        // 初始化自增列信息
        private void InitializeIdentity()
        {
            var rInfo = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            _autoIncrement = rInfo.Wrappers.FirstOrDefault(x =>
            {
                var column = (x.Value as MemberAccessWrapper).Column;
                return(column != null && column.IsIdentity);
            }).Value as MemberAccessWrapper;
        }
        // LEFT OR INNER JOIN
        private void AppendLfInJoin(SqlBuilder builder, DbExpression exp, TableAliasCache aliases)
        {
            // [TableName]
            //var constExp = exp.Expressions[0] as ConstantExpression;
            //constExp.Type.GetGenericArguments()[0]
            //var queryable = constExp.Value as IDbQueryable;
            //var innerExp = queryable.DbExpressions[0];
            //if (innerExp.DbExpressionType != DbExpressionType.GetTable) throw new XfwException("inner expression must be GetTable<T> expression");
            //Type type = (innerExp.Expression as ConstantExpression).Value as Type;

            Type type = exp.Expressions[0].Type.GetGenericArguments()[0];

            builder.Append(' ');
            builder.AppendMember(TypeRuntimeInfoCache.GetRuntimeInfo(type).TableName);

            LambdaExpression left  = exp.Expressions[1] as LambdaExpression;
            LambdaExpression right = exp.Expressions[2] as LambdaExpression;
            NewExpression    body1 = left.Body as NewExpression;
            NewExpression    body2 = right.Body as NewExpression;

            // t0(t1)
            string alias = body1 == null
                ? aliases.GetTableAlias(exp.Expressions[2])
                : aliases.GetTableAlias(body2.Arguments[0]);

            builder.Append(' ');
            builder.Append(alias);
            builder.Append(' ');

            // ON a.Name = b.Name AND a.Id = b.Id
            builder.Append("ON ");

            if (body1 == null)
            {
                builder.AppendMember(aliases, left.Body.ReduceUnary());
                builder.Append(" = ");
                builder.AppendMember(aliases, right.Body.ReduceUnary());
            }
            else
            {
                for (int index = 0; index < body1.Arguments.Count; ++index)
                {
                    builder.AppendMember(aliases, body1.Arguments[index]);
                    builder.Append(" = ");
                    builder.AppendMember(aliases, body2.Arguments[index]);
                    if (index < body1.Arguments.Count - 1)
                    {
                        builder.Append(" AND ");
                    }
                }
            }
        }
        // Cross Join
        private void AppendCrossJoin(SqlBuilder builder, DbExpression exp, TableAliasCache aliases)
        {
            LambdaExpression lambdaExp = exp.Expressions[1] as LambdaExpression;
            Type             type      = lambdaExp.Parameters[1].Type;

            builder.Append(' ');
            builder.AppendMember(TypeRuntimeInfoCache.GetRuntimeInfo(type).TableName);

            string alias = aliases.GetTableAlias(lambdaExp.Parameters[1]);

            builder.Append(' ');
            builder.Append(alias);
            builder.Append(' ');
        }
Exemplo n.º 6
0
        // 导航属性
        private void Deserialize_Navigation(object model, string typeName)
        {
            // CRM_SaleOrder.Client
            Type            pType   = model.GetType();
            TypeRuntimeInfo runtime = TypeRuntimeInfoCache.GetRuntimeInfo(pType);

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

            foreach (var kvp in _define.NavDescriptors)
            {
                var descriptor = kvp.Value;
                if (descriptor.Count == 0)
                {
                    continue;
                }

                string keyName = typeName + "." + descriptor.Name;
                if (keyName != kvp.Key)
                {
                    continue;
                }

                var navWrapper = runtime.GetWrapper(descriptor.Name);
                if (navWrapper == null)
                {
                    continue;
                }

                Type navType = navWrapper.DataType;
                Func <IDataRecord, object> func = null;
                if (!_funcCache.TryGetValue(keyName, out func))
                {
                    func = GetDeserializer(navType, _reader, _define.Columns, descriptor.Start, descriptor.Start + descriptor.Count);
                    _funcCache[keyName] = func;
                }

                object navModel = func(_reader);
                navWrapper.Set(model, navModel);

                TypeRuntimeInfo navRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navType);
                if (navRuntime.NavWrappers.Count > 0)
                {
                    Deserialize_Navigation(navModel, keyName);
                }
            }
        }
Exemplo n.º 7
0
        protected virtual void VisitNavigation(Expression node, string memberName = null)
        {
            // 表达式 => b.Client.Address.AddressName
            Expression f = node;
            Stack <KeyValuePair <string, MemberExpression> > stack = null;

            while (f != null && f.IsVisitable())
            {
                if (f.NodeType != ExpressionType.MemberAccess)
                {
                    break;
                }

                if (stack == null)
                {
                    stack = new Stack <KeyValuePair <string, MemberExpression> >();
                }
                MemberExpression m            = f as MemberExpression;
                var runtime                   = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type);
                ForeignKeyAttribute attribute = runtime.GetWrapperAttribute <ForeignKeyAttribute>(m.Member.Name);
                if (attribute == null)
                {
                    break;
                }

                string key = m.GetKeyWidthoutAnonymous();
                stack.Push(new KeyValuePair <string, MemberExpression>(key, m));
                f = m.Expression;
            }

            if (stack != null && stack.Count > 0)
            {
                while (stack != null && stack.Count > 0)
                {
                    KeyValuePair <string, MemberExpression> kvp = stack.Pop();
                    string           key = kvp.Key;
                    MemberExpression m   = kvp.Value;

                    var runtime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Type);
                    // 检查查询表达式是否显示指定该表关联
                    string alias = _aliases.GetJoinTableAlias(runtime.TableName);
                    if (string.IsNullOrEmpty(alias))
                    {
                        // 如果没有,则使用导航属性别名
                        alias = _aliases.GetNavigationTableAlias(key);
                        if (!_navigations.ContainsKey(kvp.Key))
                        {
                            _navigations.Add(kvp);
                        }
                    }

                    if (stack.Count == 0 && !string.IsNullOrEmpty(memberName))
                    {
                        _builder.AppendMember(alias, memberName);
                    }
                }
            }
            else
            {
                // => SelectMany 也会产生类似 'b.Client.Address.AddressName' 这样的表达式
                string alias = _aliases.GetTableAlias(node);
                _builder.AppendMember(alias, memberName);
            }

            //return f;
        }
            // 添加导航属性关联
            protected virtual void AppendNavigation()
            {
                if (this.AdditionForeigns == null || this.AdditionForeigns.Count == 0)
                {
                    return;
                }

                //开始产生LEFT JOIN 子句
                SqlBuilder builder = this.JoinFragment;

                foreach (var kvp in _navigations)
                {
                    string           key          = kvp.Key;
                    MemberExpression m            = kvp.Value;
                    var runtime                   = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type);
                    ForeignKeyAttribute attribute = runtime.GetWrapperAttribute <ForeignKeyAttribute>(m.Member.Name);

                    string innerKey   = string.Empty;
                    string outerKey   = key;
                    string innerAlias = string.Empty;

                    if (!m.Expression.IsVisitable())
                    {
                        innerKey = m.Expression.NodeType == ExpressionType.Parameter
                            ? (m.Expression as ParameterExpression).Name
                            : (m.Expression as MemberExpression).Member.Name;
                    }
                    else
                    {
                        MemberExpression mLeft = m.Expression as MemberExpression;
                        string           name  = TypeRuntimeInfoCache.GetRuntimeInfo(mLeft.Type).TableName;
                        innerAlias = _aliases.GetJoinTableAlias(name);

                        if (string.IsNullOrEmpty(innerAlias))
                        {
                            string keyLeft = mLeft.GetKeyWidthoutAnonymous();
                            if (_navigations.ContainsKey(keyLeft))
                            {
                                innerKey = keyLeft;
                            }
                        }
                    }

                    string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _aliases.GetTableAlias(innerKey);
                    string alias2 = _aliases.GetTableAlias(outerKey);


                    builder.AppendNewLine();
                    builder.Append("LEFT JOIN ");
                    Type pType = m.Type;
                    //不实现一对多映射
                    //if (pType.IsGenericType) pType = pType.GetGenericArguments()[0];
                    builder.AppendMember(TypeRuntimeInfoCache.GetRuntimeInfo(pType).TableName);
                    builder.Append(" ");
                    builder.Append(alias2);
                    builder.Append(" ON ");
                    for (int i = 0; i < attribute.InnerKeys.Length; i++)
                    {
                        builder.Append(alias1);
                        builder.Append('.');
                        builder.AppendMember(attribute.InnerKeys[i]);
                        builder.Append(" = ");
                        builder.Append(alias2);
                        builder.Append('.');
                        builder.AppendMember(attribute.OuterKeys[i]);

                        if (i < attribute.InnerKeys.Length - 1)
                        {
                            builder.Append(" AND ");
                        }
                    }
                }
            }
Exemplo n.º 9
0
        /// <summary>
        /// 将 <see cref="IDataRecord"/> 映射为实体
        /// </summary>
        /// <typeparam reader="T">数据源</typeparam>
        /// <param name="reader">数据源</param>
        /// <param name="define">命令定义</param>
        /// <returns></returns>
        public static T ToModel <T>(this IDataRecord reader, CommandDefine define = null)
        {
            object obj = null;

            object[] values = null;
            int      index  = 0;

            // 基元类初始化 ########################
            if (Reflection.TypeUtils.IsPrimitive(typeof(T)))
            {
                //if(reader.IsDBNull(0)) return default(T)
                //obj = reader.GetValue(0);
                //return obj is DBNull ? default(T) : (T)obj;
                return(reader.IsDBNull(0) ? default(T) : (T)reader.GetValue(0));
            }

            // 匿名类初始化 ########################
            TypeRuntimeInfo runtime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            Inte.XFramework.Reflection.Emit.ConstructorInvoker ctor = runtime.ConstructInvoker;
            if (runtime.IsAnonymousType)
            {
                values = new object[reader.FieldCount];
                reader.GetValues(values);
                for (index = 0; index < values.Length; ++index)
                {
                    if (values[index] is DBNull)
                    {
                        values[index] = null;
                    }
                }
                return((T)ctor.Invoke(values));
            }

            // 实体类初始化 ########################
            T model = (T)ctor.Invoke();

            values = new object[reader.FieldCount];
            reader.GetValues(values);

            // 计算导航属性所占用的索引,这些索引对应的值不会赋给 T 实体
            var sc = define as CommandDefine_Select;

            if (sc == null || (sc.NavDescriptors != null && sc.NavDescriptors.Count == 0))
            {
                // 直接跑SQL,则不解析导航属性
                for (int i = 0; i < reader.FieldCount; ++i)
                {
                    obj = values[i];
                    if (obj == DBNull.Value)
                    {
                        continue;
                    }

                    string name    = reader.GetName(i);
                    var    wrapper = runtime.GetWrapper(name) as MemberAccessWrapper;
                    if (wrapper != null)
                    {
                        SetProperty(model, wrapper, obj);
                    }
                }
            }
            else
            {
                // 使用表达式查询,解析导航属性
                bool nav = sc.NavDescriptors.Any(x => x.Value.Count > 0);
                int  min = nav ? sc.NavDescriptors.Min(x => x.Value.Start) : 0;

                // 第一层
                index = -1;
                foreach (var kvp in sc.Columns)
                {
                    index += 1;
                    obj    = values[index];

                    if (obj == DBNull.Value)
                    {
                        continue;
                    }
                    if (nav && index >= min)
                    {
                        break;
                    }

                    var wrapper = runtime.GetWrapper(kvp.Value.Name) as MemberAccessWrapper;
                    if (wrapper != null)
                    {
                        SetProperty(model, wrapper, obj);
                    }
                }

                // 递归导航属性
                if (runtime.NavWrappers.Count > 0)
                {
                    ToModel_Navigation(model, values, sc, string.Empty);
                }
            }

            return(model);
        }
Exemplo n.º 10
0
        // 导航属性
        private static void ToModel_Navigation(object model, object[] values, CommandDefine_Select define, string typeName)
        {
            // CRM_SaleOrder.Client
            Type            pType   = model.GetType();
            TypeRuntimeInfo runtime = TypeRuntimeInfoCache.GetRuntimeInfo(pType);

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

            foreach (var kvp in runtime.NavWrappers)
            {
                string keyName = typeName + "." + kvp.Key;
                ColumnNavDescriptor descriptor = null;
                define.NavDescriptors.TryGetValue(keyName, out descriptor);
                if (descriptor == null)
                {
                    continue;
                }

                // 实例化这个导航属性并且给它赋值
                var             navWrapper = kvp.Value;
                Type            navType    = navWrapper.DataType;
                TypeRuntimeInfo navRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navType);
                object          navModel   = navRuntime.ConstructInvoker.Invoke();

                if (descriptor.Count > 0)
                {
                    int index = -1;
                    foreach (var c_kvp in define.Columns)
                    {
                        index += 1;
                        if (index < descriptor.Start)
                        {
                            continue;
                        }
                        if (index > (descriptor.Start + descriptor.Count))
                        {
                            break;
                        }

                        object obj = values[index];
                        if (obj == DBNull.Value)
                        {
                            continue;
                        }

                        var wrapper = navRuntime.GetWrapper(c_kvp.Value.Name) as MemberAccessWrapper;
                        if (wrapper != null)
                        {
                            SetProperty(navModel, wrapper, obj);
                        }
                    }
                }

                SetProperty(model, navWrapper, navModel);

                if (navRuntime.NavWrappers.Count > 0)
                {
                    ToModel_Navigation(navModel, values, define, keyName);
                }
            }
        }
Exemplo n.º 11
0
 /// <summary>
 /// 取指定类型的运行时元数据
 /// </summary>
 /// <typeparam name="T">T</typeparam>
 /// <returns></returns>
 public static TypeRuntimeInfo GetRuntimeInfo <T>()
 {
     return(TypeRuntimeInfoCache.GetRuntimeInfo(typeof(T)));
 }
Exemplo n.º 12
0
        /// <summary>
        /// 将 <see cref="IDataRecord"/> 上的当前行反序列化为实体
        /// </summary>
        /// <returns></returns>
        public T Deserialize()
        {
            #region 基元类型

            if (Reflection.TypeUtils.IsPrimitive(typeof(T)))
            {
                if (_reader.IsDBNull(0))
                {
                    return(default(T));
                }

                var obj = _reader.GetValue(0);
                if (obj.GetType() != typeof(T))
                {
                    obj = Convert.ChangeType(obj, typeof(T));
                }

                return((T)obj);
            }

            #endregion

            #region 匿名类型

            TypeRuntimeInfo runtime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();
            Inte.XFramework.Reflection.Emit.ConstructorInvoker ctor = runtime.ConstructInvoker;
            if (runtime.IsAnonymousType)
            {
                object[] values = new object[_reader.FieldCount];
                _reader.GetValues(values);
                for (int index = 0; index < values.Length; ++index)
                {
                    if (values[index] is DBNull)
                    {
                        values[index] = null;
                    }
                }
                return((T)ctor.Invoke(values));
            }

            #endregion

            #region 实体类型

            T model = default(T);
            if (_define == null || (_define.NavDescriptors != null && _define.NavDescriptors.Count == 0))
            {
                // 直接跑SQL,则不解析导航属性
                if (_topLevel == null)
                {
                    _topLevel = GetDeserializer(typeof(T), _reader);
                }
                model = (T)_topLevel(_reader);
            }
            else
            {
                // 第一层
                if (_topLevel == null)
                {
                    _topLevel = GetDeserializer(typeof(T), _reader, _define.Columns, 0, _define.NavDescriptors.MinIndex);
                }
                model = (T)_topLevel(_reader);

                // 递归导航属性
                this.Deserialize_Navigation(model, string.Empty);
            }

            #endregion


            return(model);
        }
Exemplo n.º 13
0
        private static Func <IDataRecord, object> GetDeserializer(Type modelType, IDataRecord reader, IDictionary <string, Column> columns = null, int start = 0, int?end = null)
        {
            string          methodName = Guid.NewGuid().ToString();
            DynamicMethod   dm         = new DynamicMethod(methodName, typeof(object), new[] { typeof(IDataRecord) }, true);
            ILGenerator     g          = dm.GetILGenerator();
            TypeRuntimeInfo runtime    = TypeRuntimeInfoCache.GetRuntimeInfo(modelType);

            var model = g.DeclareLocal(modelType);

            g.Emit(OpCodes.Newobj, runtime.ConstructInvoker.Constructor);
            g.Emit(OpCodes.Stloc, model);

            if (end == null)
            {
                end = reader.FieldCount;
            }
            for (int index = start; index < end; index++)
            {
                string keyName = reader.GetName(index);
                if (columns != null)
                {
                    Column column = null;
                    columns.TryGetValue(keyName, out column);
                    keyName = column != null ? column.Name : string.Empty;
                }

                var wrapper = runtime.GetWrapper(keyName);// as MemberAccessWrapper;
                if (wrapper == null)
                {
                    continue;
                }

                var isDBNullLabel = g.DefineLabel();
                g.Emit(OpCodes.Ldarg_0);
                g.Emit(OpCodes.Ldc_I4, index);
                g.Emit(OpCodes.Callvirt, _isDBNull);
                g.Emit(OpCodes.Brtrue, isDBNullLabel);

                var m_method = GetReaderMethod(wrapper.DataType);
                g.Emit(OpCodes.Ldloc, model);
                g.Emit(OpCodes.Ldarg_0);
                g.Emit(OpCodes.Ldc_I4, index);
                g.Emit(OpCodes.Callvirt, m_method);

                Type dataType           = wrapper.DataType;
                Type nullUnderlyingType = dataType.IsGenericType ? Nullable.GetUnderlyingType(dataType) : null;
                Type unboxType          = nullUnderlyingType != null ? nullUnderlyingType : dataType;

                if (unboxType == typeof(byte[]) || (m_method == _getValue && dataType != typeof(object)))
                {
                    g.Emit(OpCodes.Castclass, dataType);
                }
                if (nullUnderlyingType != null)
                {
                    g.Emit(OpCodes.Newobj, dataType.GetConstructor(new[] { nullUnderlyingType }));
                }

                if (wrapper.Member.MemberType == MemberTypes.Field)
                {
                    g.Emit(OpCodes.Stfld, wrapper.FieldInfo);
                }
                else
                {
                    g.Emit(OpCodes.Callvirt, wrapper.SetMethod);
                }

                g.MarkLabel(isDBNullLabel);
            }


            g.Emit(OpCodes.Ldloc, model);
            g.Emit(OpCodes.Ret);

            var func = (Func <IDataRecord, object>)dm.CreateDelegate(typeof(Func <IDataRecord, object>));

            return(func);
        }