Пример #1
0
        /// <summary>
        /// 将一个 <see cref="DataRow"/> 转换为一个 <typeparamref name="T"/> 的对象。
        /// </summary>
        /// <param name="row">一个 <see cref="DataRow"/> 对象。</param>
        /// <returns>由 <see cref="DataRow"/> 中数据转换成的 <typeparamref name="T"/> 对象实例。</returns>
        public virtual T Map(DataRow row)
        {
            var converter = ConvertManager.GetConverter(typeof(T));

            if (converter != null)
            {
                return((T)converter.ConvertFrom(row[0], row.Table.Columns[0].DataType.GetDbType()));
            }

            return(row[0].To <object, T>());
        }
Пример #2
0
        internal static TC ToTypeEx <TS, TC>(this TS value)
        {
            var converter = ConvertManager.GetConverter(typeof(TC));

            if (converter != null)
            {
                return((TC)converter.ConvertFrom(value, typeof(TC).GetDbType()));
            }

            return(value.To <TS, TC>());
        }
Пример #3
0
        protected override Expression VisitColumn(ColumnExpression column)
        {
            ParameterExpression recordWrapper;
            ParameterExpression dataReader;
            int ordinal;

            if (scope != null && scope.TryGetValue(column, out recordWrapper, out dataReader, out ordinal))
            {
                if (!column.Type.IsDbTypeSupported())
                {
                    throw new InvalidCastException(SR.GetString(SRKind.InvalidCastPropertyValue, column.Type.FullName));
                }

                //把 ColumnExpression 换成 RecordWrapper.GetInt32(IDataReader, int) 这样的表达式
                var dbType = column.MapInfo != null && column.MapInfo.DataType != null ?
                             (DbType)column.MapInfo.DataType : column.Type.GetDbType();

                var        method     = RecordWrapHelper.GetMethodByOrdinal(dbType);
                Expression expression = Expression.Call(recordWrapper, method, dataReader, Expression.Constant(ordinal));

                //先找转换器
                var converter = ConvertManager.GetConverter(column.Type);
                if (converter != null)
                {
                    //调用ConvertManager.GetConverter
                    var mconverter = Expression.Call(null, MthGetConverter, Expression.Constant(column.Type));

                    //调用 IValueConverter.ConvertFrom
                    expression = (Expression)Expression.Convert(
                        Expression.Call(mconverter, MthConvert, expression, Expression.Constant(dbType)),
                        column.Type);
                }
                else
                {
                    if (column.Type.IsNullableType())
                    {
                        //调用 RecordWrapper.IsDbNull 判断值是否为空
                        expression = (Expression)Expression.Condition(
                            Expression.Call(recordWrapper, MthIsDbNull, dataReader, Expression.Constant(ordinal)),
                            Expression.Convert(Expression.Constant(null), column.Type),
                            Expression.Convert(expression, column.Type));
                    }
                    else if (column.Type != method.ReturnType)
                    {
                        expression = (Expression)Expression.Convert(expression, column.Type);
                    }
                }

                return(expression);
            }

            return(column);
        }
Пример #4
0
        /// <summary>
        /// 将一个 <see cref="IDataReader"/> 转换为一个 <typeparamref name="T"/> 的对象。
        /// </summary>
        /// <param name="database">当前的 <see cref="IDatabase"/> 对象。</param>
        /// <param name="reader">一个 <see cref="IDataReader"/> 对象。</param>
        /// <returns>由当前 <see cref="IDataReader"/> 对象中的数据转换成的 <typeparamref name="T"/> 对象实例。</returns>
        public virtual T Map(IDatabase database, IDataReader reader)
        {
            var value = RecordWrapper == null ? reader[0] :
                        RecordWrapper.GetValue(reader, 0);

            var converter = ConvertManager.GetConverter(typeof(T));

            if (converter != null)
            {
                return((T)converter.ConvertFrom(value, reader.GetFieldType(0).GetDbType()));
            }

            return(value.To <object, T>());
        }
Пример #5
0
        /// <summary>
        /// 将一个 <see cref="IDataReader"/> 转换为一个 <typeparamref name="T"/> 的对象。
        /// </summary>
        /// <param name="reader">一个 <see cref="IDataReader"/> 对象。</param>
        /// <returns>由当前 <see cref="IDataReader"/> 对象中的数据转换成的 <typeparamref name="T"/> 对象实例。</returns>
        public virtual T Map(IDataReader reader)
        {
            var index = reader.FieldCount != 1 ? 1 : 0;
            var value = RecordWrapper == null ? reader[index] :
                        RecordWrapper.GetValue(reader, index);

            var converter = ConvertManager.GetConverter(typeof(T));

            if (converter != null)
            {
                return((T)converter.ConvertFrom(value, reader.GetFieldType(index).GetDbType()));
            }

            return(value.To <object, T>());
        }
Пример #6
0
        /// <summary>
        /// 使用当前的记录填充数组。
        /// </summary>
        /// <param name="mappings">名称和类型的映射字典。</param>
        /// <param name="item">当前的数据项。</param>
        /// <param name="data">数组的数组。</param>
        /// <param name="batch">当前批次中的索引。</param>
        private void FillArrayData(IEnumerable <PropertyFieldMapping> mappings, object item, object[][] data, int batch)
        {
            mappings.ForEach((m, i) =>
            {
                var value = m.ValueFunc(item);
                if (value != null)
                {
                    var converter = ConvertManager.GetConverter(m.PropertyType);
                    if (converter != null)
                    {
                        value = converter.ConvertTo(value, m.FieldType);
                    }
                }

                data[i][batch] = value;
            });
        }
Пример #7
0
        private PropertyValue GetConvertedValue(PropertyMapping mapper, bool isNull, Func <int, object> funcGetValue)
        {
            var converter = ConvertManager.GetConverter(mapper.Property.Type);

            if (converter == null)
            {
                throw new NotSupportedException(SR.GetString(SRKind.UnableConvertComplexType, mapper.Property.Type));
            }

            if (isNull)
            {
                return(PropertyValue.Empty);
            }

            var dbType = mapper.Property.Info.DataType ?? DbType.String;

            return(PropertyValue.NewValue(converter.ConvertFrom(funcGetValue(mapper.Index), dbType)));
        }
Пример #8
0
        /// <summary>
        /// 获取受 <see cref="IValueConverter"/> 支持的数据转换值。
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        private static object GetConvertableValue(IEntity entity, IProperty property)
        {
            var value = entity.GetValue(property);

            if (!PropertyValue.IsEmpty(value))
            {
                //查找属性类型对应的转换器
                var converter = ConvertManager.GetConverter(property.Type);
                if (converter != null && property.Info.DataType != null)
                {
                    var pvValue = value.GetValue();
                    return(converter.ConvertTo(pvValue, (DbType)property.Info.DataType));
                }

                return(value.GetValue());
            }

            return(property.Type.GetDefaultValue());
        }
Пример #9
0
        /// <summary>
        /// 使用当前的记录填充数组。
        /// </summary>
        /// <param name="mappings">名称和类型的映射字典。</param>
        /// <param name="item">当前的数据项。</param>
        /// <param name="data">数组的数组。</param>
        /// <param name="batch">当前批次中的索引。</param>
        private void FillArrayData(IEnumerable <PropertyFieldMapping> mappings, object item, object[][] data, int batch)
        {
            var i = 0;

            foreach (var map in mappings)
            {
                var value = map.ValueFunc(item);
                if (value != null)
                {
                    var converter = ConvertManager.GetConverter(map.PropertyType);
                    if (converter != null)
                    {
                        value = converter.ConvertTo(value, map.FieldType);
                    }
                }

                data[i++][batch] = value;
            }
        }
Пример #10
0
        /// <summary>
        /// 获取受 <see cref="IValueConverter"/> 支持的数据转换值。
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        private static object GetConvertableValue(IEntity entity, IProperty property)
        {
            var value = entity.InternalGetValue(property);

            if (!value.IsNullOrEmpty())
            {
                var converter = ConvertManager.GetConverter(property.Type);
                if (converter != null)
                {
                    var storageValue = value.GetStorageValue();
                    var convertValue = converter.ConvertTo(storageValue, (DbType)property.Info.DataType);
                    return(convertValue);
                }

                return(value.GetStorageValue());
            }

            return(property.Type.GetDefaultValue());
        }
Пример #11
0
        internal static NamedValueExpression GetNamedValueExpression(string name, Expression value, DbType dbType)
        {
            var exp = value;

            if (exp.NodeType == ExpressionType.Convert)
            {
                exp = ((UnaryExpression)value).Operand;
            }

            if (exp.NodeType != ExpressionType.Constant)
            {
                return(new NamedValueExpression(name, exp));
            }

            IValueConverter converter;

            if ((converter = ConvertManager.GetConverter(exp.Type)) != null)
            {
                exp = Expression.Constant(converter.ConvertTo(((ConstantExpression)exp).Value, dbType));
                exp = Expression.Convert(exp, typeof(object));
            }

            return(new NamedValueExpression(name, exp, dbType));
        }
Пример #12
0
        /// <summary>
        /// 根据指定的<see cref="PropertyValue"/> 来设置 <see cref="Parameter"/> 的值。
        /// </summary>
        /// <param name="value"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public static Parameter Parametrization(PropertyValue value, Parameter parameter)
        {
            switch (value.StorageType)
            {
            case StorageType.Boolean:
                parameter.Value  = value.Boolean;
                parameter.DbType = DbType.Boolean;
                break;

            case StorageType.Byte:
                parameter.Value  = value.Byte;
                parameter.DbType = DbType.Byte;
                break;

            case StorageType.ByteArray:
                parameter.Value  = value.ByteArray;
                parameter.DbType = DbType.Binary;
                break;

            case StorageType.Char:
                parameter.Value  = value.Char;
                parameter.DbType = DbType.AnsiString;
                break;

            case StorageType.DateTime:
                parameter.Value  = value.DateTime;
                parameter.DbType = DbType.DateTime;
                break;

            case StorageType.Decimal:
                parameter.Value  = value.Decimal;
                parameter.DbType = DbType.Decimal;
                break;

            case StorageType.Double:
                parameter.Value  = value.Double;
                parameter.DbType = DbType.Double;
                break;

            case StorageType.Enum:
                parameter.Value  = value.Enum.To <int>();
                parameter.DbType = DbType.Int32;
                break;

            case StorageType.Guid:
                parameter.Value  = value.Guid;
                parameter.DbType = DbType.Guid;
                break;

            case StorageType.Int16:
                parameter.Value  = value.Int16;
                parameter.DbType = DbType.Int16;
                break;

            case StorageType.Int32:
                parameter.Value  = value.Int32;
                parameter.DbType = DbType.Int32;
                break;

            case StorageType.Int64:
                parameter.Value  = value.Int64;
                parameter.DbType = DbType.Int64;
                break;

            case StorageType.Single:
                parameter.Value  = value.Single;
                parameter.DbType = DbType.Single;
                break;

            case StorageType.String:
                parameter.Value  = value.String;
                parameter.DbType = DbType.AnsiString;
                break;

            case StorageType.TimeSpan:
                parameter.Value  = value.TimeSpan;
                parameter.DbType = DbType.Time;
                break;

            case StorageType.Object:
                var converter = ConvertManager.GetConverter(value.Object.GetType());
                if (converter != null)
                {
                    var dbType = value.DataType ?? DbType.String;
                    parameter.Value  = converter.ConvertTo(value.Object, dbType);
                    parameter.DbType = dbType;
                }
                break;
            }

            return(parameter);
        }
Пример #13
0
        private Expression BuildExecuteBatch(BatchCommandExpression batch)
        {
            var operation = Parameterize(batch.Operation.Body);

            var result      = _translator.Translate(operation);
            var namedValues = NamedValueGatherer.Gather(operation);

            var table = new DataTable();

            foreach (var nv in namedValues)
            {
                var info = GetPropertyInfoFromExpression(nv.Value);
                if (info != null)
                {
                    table.Columns.Add(nv.Name, info.DataType.Value.FromDbType());
                }
                else
                {
                    table.Columns.Add(nv.Name, DataExpressionRow.CreateType(nv.Value.Type));
                }
            }

            var parameters = namedValues.ToDictionary(s => s.Name, s =>
            {
                var expression = s.Value;
                var info       = GetPropertyInfoFromExpression(expression);
                if (info == null)
                {
                    return(expression);
                }

                if (ConvertManager.GetConverter(expression.Type) != null)
                {
                    var convExp = Expression.Call(null, MethodCache.GetConverter, Expression.Constant(expression.Type));
                    expression  = Expression.Call(convExp, MethodCache.ConvertTo, expression, Expression.Constant((DbType)info.DataType));
                }

                return((object)Expression.Lambda(expression, batch.Operation.Parameters[1]).Compile());
            });

            var entities = (IEnumerable)batch.Input.Value;

            foreach (IEntity entity in entities)
            {
                var row = table.NewRow();
                foreach (var nv in parameters)
                {
                    if (nv.Value is Delegate del)
                    {
                        row[nv.Key] = del.DynamicInvoke(entity) ?? DBNull.Value;
                    }
                    else if (nv.Value is Expression exp)
                    {
                        exp = ParameterRewriter.Rewrite(exp, batch.Operation.Parameters[1], entity);
                        var setter = Expression.Lambda(exp, _executor).Compile();
                        row[nv.Key] = DataExpressionRow.Create(exp.Type, setter);
                    }
                }

                table.Rows.Add(row);
            }

            Expression plan;

            if (_isAsync)
            {
                _cancelToken = Expression.Parameter(typeof(CancellationToken), "token");
                plan         = Expression.Call(_executor, MethodCache.DbUpdateAsync,
                                               Expression.Constant(table),
                                               Expression.Constant((SqlCommand)result.QueryText),
                                               Expression.Constant(null, typeof(SqlCommand)),
                                               Expression.Constant(null, typeof(SqlCommand)),
                                               _cancelToken
                                               );
            }
            else
            {
                plan = Expression.Call(_executor, MethodCache.DbUpdate,
                                       Expression.Constant(table),
                                       Expression.Constant((SqlCommand)result.QueryText),
                                       Expression.Constant(null, typeof(SqlCommand)),
                                       Expression.Constant(null, typeof(SqlCommand))
                                       );
            }

            if (operation.NodeType != (ExpressionType)DbExpressionType.Insert)
            {
                return(plan);
            }

            return(Expression.Call(typeof(ExecutionBuilder),
                                   _isAsync ? nameof(ExecutionBuilder.UpdateEntitiesAsync) : nameof(ExecutionBuilder.UpdateEntities), null,
                                   plan,
                                   Expression.Constant(table, typeof(DataTable)),
                                   Expression.Constant(entities, typeof(IEnumerable))));
        }