/// <summary> /// 获取是否支持数据类型。 /// </summary> /// <param name="type"></param> /// <returns></returns> public static bool IsDbTypeSupported(this Type type) { Guard.ArgumentNull(type, "type"); type = type.GetNonNullableType(); var typeCode = Type.GetTypeCode(type); if (ConvertManager.CanConvert(type)) { return(true); } return(typeCode != TypeCode.Object && typeCode != TypeCode.Empty && typeCode != TypeCode.DBNull); }
protected override Expression VisitColumn(ColumnExpression column) { if (_scope != null && _scope.TryGetValue(column, out ParameterExpression recordWrapper, out ParameterExpression dataReader, out int 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)); //先找转换器 if (ConvertManager.CanConvert(column.Type)) { //调用ConvertManager.GetConverter var converter = Expression.Call(null, MethodCache.GetConverter, Expression.Constant(column.Type)); //调用 IValueConverter.ConvertFrom expression = Expression.Convert( Expression.Call(converter, MethodCache.ConvertFrom, expression, Expression.Constant(dbType)), column.Type); } else { if (column.Type.IsNullableType()) { //调用 RecordWrapper.IsDbNull 判断值是否为空 expression = Expression.Condition( Expression.Call(recordWrapper, MethodCache.IsDbNull, dataReader, Expression.Constant(ordinal)), Expression.Convert(Expression.Constant(null), column.Type), Expression.Convert(expression, column.Type)); } else if (column.Type != method.ReturnType) { expression = Expression.Convert(expression, column.Type); } } return(expression); } return(column); }
private void CompileFunction(IDataReader reader) { var newExp = Expression.New(typeof(T)); var mapping = GetMapping(GetDataReaderFields(reader)); var rowMapExp = Expression.Constant(RecordWrapper); var parExp = Expression.Parameter(typeof(IDataRecord), "s"); var bindings = mapping.Select(s => { var dbType = reader.GetFieldType(s.Index); var getValueMethod = Data.RecordWrapper.RecordWrapHelper.GetMethodByOrdinal(dbType.GetDbType()); var expression = (Expression)Expression.Call(rowMapExp, getValueMethod, new Expression[] { parExp, Expression.Constant(s.Index) }); if (ConvertManager.CanConvert(s.Info.PropertyType)) { var converter = Expression.Call(typeof(ConvertManager), nameof(ConvertManager.GetConverter), null, Expression.Constant(s.Info.PropertyType)); expression = Expression.Call(converter, MethodCache.ConvertFrom, Expression.Convert(expression, typeof(object)), Expression.Constant(dbType.GetDbType())); expression = Expression.Convert(expression, s.Info.PropertyType); } else if (s.Info.PropertyType.IsNullableType()) { expression = Expression.Condition( Expression.Call(parExp, MethodCache.IsDBNull, Expression.Constant(s.Index, typeof(int))), Expression.Convert(Expression.Constant(null), s.Info.PropertyType), Expression.Convert(expression, s.Info.PropertyType)); } else if (dbType != s.Info.PropertyType) { expression = Expression.Convert(expression, s.Info.PropertyType); } return(Expression.Bind(s.Info, expression)); }); var expr = Expression.Lambda <Func <IDataReader, T> >( Expression.MemberInit( newExp, bindings.ToArray()), parExp); _funcDataRecd = expr.Compile(); }