/Signum.Engine/Connection/FieldReader.cs
C# | 611 lines | 542 code | 69 blank | 0 comment | 56 complexity | 30e180d1406a65ae047ee5b8d818b5c1 MD5 | raw file
Possible License(s): GPL-3.0
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Data.SqlClient;
- using Signum.Utilities.Reflection;
- using System.Linq.Expressions;
- using System.Reflection;
- using Signum.Utilities;
- using Signum.Engine.Maps;
- using Signum.Entities;
- using System.Data.SqlTypes;
- using System.Data.Common;
- using Microsoft.SqlServer.Types;
- using Microsoft.SqlServer.Server;
- using Signum.Utilities.ExpressionTrees;
-
- namespace Signum.Engine
- {
- public class FieldReader
- {
- DbDataReader reader;
- TypeCode[] typeCodes;
-
- private const TypeCode tcGuid = (TypeCode)20;
- private const TypeCode tcTimeSpan = (TypeCode)21;
- private const TypeCode tcDateTimeOffset = (TypeCode)22;
-
- public int LastOrdinal;
-
- TypeCode GetTypeCode(int ordinal)
- {
- Type type = reader.GetFieldType(ordinal);
- TypeCode tc = Type.GetTypeCode(type);
- if (tc == TypeCode.Object)
- {
- if (type == typeof(Guid))
- tc = tcGuid;
-
- if (type == typeof(TimeSpan))
- tc = tcTimeSpan;
-
- if (type == typeof(DateTimeOffset))
- tc = tcDateTimeOffset;
- }
- return tc;
- }
-
- public FieldReader(DbDataReader reader)
- {
- this.reader = reader;
-
- this.typeCodes = new TypeCode[reader.FieldCount];
- for (int i = 0; i < typeCodes.Length; i++)
- typeCodes[i] = GetTypeCode(i);
- }
-
- public bool IsNull(int ordinal)
- {
- LastOrdinal = ordinal;
- return reader.IsDBNull(ordinal);
- }
-
- public string GetString(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
-
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return reader.GetByte(ordinal).ToString();
- case TypeCode.Int16:
- return reader.GetInt16(ordinal).ToString();
- case TypeCode.Int32:
- return reader.GetInt32(ordinal).ToString();
- case TypeCode.Int64:
- return reader.GetInt64(ordinal).ToString();
- case TypeCode.Double:
- return reader.GetDouble(ordinal).ToString();
- case TypeCode.Single:
- return reader.GetFloat(ordinal).ToString();
- case TypeCode.Decimal:
- return reader.GetDecimal(ordinal).ToString();
- case TypeCode.DateTime:
- return reader.GetDateTime(ordinal).ToString();
- case tcGuid:
- return reader.GetGuid(ordinal).ToString();
- case TypeCode.String:
- return reader.GetString(ordinal);
- default:
- return reader.GetValue(ordinal).ToString();
- }
- }
-
- public byte[] GetByteArray(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
-
- return (byte[])reader.GetValue(ordinal);
- }
-
- public bool GetBoolean(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Boolean:
- return reader.GetBoolean(ordinal);
- case TypeCode.Byte:
- return reader.GetByte(ordinal) != 0;
- case TypeCode.Int16:
- return reader.GetInt16(ordinal) != 0;
- case TypeCode.Int32:
- return reader.GetInt32(ordinal) != 0;
- case TypeCode.Int64:
- return reader.GetInt64(ordinal) != 0;
- case TypeCode.String:
- return bool.Parse(reader.GetString(ordinal));
- default:
- return ReflectionTools.ChangeType<bool>(reader.GetValue(ordinal));
- }
- }
-
- public bool? GetNullableBoolean(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetBoolean(ordinal);
- }
-
-
- public Byte GetByte(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return reader.GetByte(ordinal);
- case TypeCode.Int16:
- return (Byte)reader.GetInt16(ordinal);
- case TypeCode.Int32:
- return (Byte)reader.GetInt32(ordinal);
- case TypeCode.Int64:
- return (Byte)reader.GetInt64(ordinal);
- case TypeCode.Double:
- return (Byte)reader.GetDouble(ordinal);
- case TypeCode.Single:
- return (Byte)reader.GetFloat(ordinal);
- case TypeCode.Decimal:
- return (Byte)reader.GetDecimal(ordinal);
- default:
- return ReflectionTools.ChangeType<Byte>(reader.GetValue(ordinal));
- }
- }
-
- public Byte? GetNullableByte(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetByte(ordinal);
- }
-
-
- public Char GetChar(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return (Char)reader.GetByte(ordinal);
- case TypeCode.Int16:
- return (Char)reader.GetInt16(ordinal);
- case TypeCode.Int32:
- return (Char)reader.GetInt32(ordinal);
- case TypeCode.Int64:
- return (Char)reader.GetInt64(ordinal);
- case TypeCode.Double:
- return (Char)reader.GetDouble(ordinal);
- case TypeCode.Single:
- return (Char)reader.GetFloat(ordinal);
- case TypeCode.Decimal:
- return (Char)reader.GetDecimal(ordinal);
- default:
- return ReflectionTools.ChangeType<Char>(reader.GetValue(ordinal));
- }
- }
-
- public Char? GetNullableChar(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetChar(ordinal);
- }
-
-
- public Single GetFloat(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return (Single)reader.GetByte(ordinal);
- case TypeCode.Int16:
- return (Single)reader.GetInt16(ordinal);
- case TypeCode.Int32:
- return (Single)reader.GetInt32(ordinal);
- case TypeCode.Int64:
- return (Single)reader.GetInt64(ordinal);
- case TypeCode.Double:
- return (Single)reader.GetDouble(ordinal);
- case TypeCode.Single:
- return reader.GetFloat(ordinal);
- case TypeCode.Decimal:
- return (Single)reader.GetDecimal(ordinal);
- default:
- return ReflectionTools.ChangeType<Single>(reader.GetValue(ordinal));
- }
- }
-
- public Single? GetNullableFloat(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetFloat(ordinal);
- }
-
-
- public Double GetDouble(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return (Double)reader.GetByte(ordinal);
- case TypeCode.Int16:
- return (Double)reader.GetInt16(ordinal);
- case TypeCode.Int32:
- return (Double)reader.GetInt32(ordinal);
- case TypeCode.Int64:
- return (Double)reader.GetInt64(ordinal);
- case TypeCode.Double:
- return reader.GetDouble(ordinal);
- case TypeCode.Single:
- return (Double)reader.GetFloat(ordinal);
- case TypeCode.Decimal:
- return (Double)reader.GetDecimal(ordinal);
- default:
- return ReflectionTools.ChangeType<Double>(reader.GetValue(ordinal));
- }
- }
-
- public Double? GetNullableDouble(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetDouble(ordinal);
- }
-
-
- public Decimal GetDecimal(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return (Decimal)reader.GetByte(ordinal);
- case TypeCode.Int16:
- return (Decimal)reader.GetInt16(ordinal);
- case TypeCode.Int32:
- return (Decimal)reader.GetInt32(ordinal);
- case TypeCode.Int64:
- return (Decimal)reader.GetInt64(ordinal);
- case TypeCode.Double:
- return (Decimal)reader.GetDouble(ordinal);
- case TypeCode.Single:
- return (Decimal)reader.GetFloat(ordinal);
- case TypeCode.Decimal:
- return reader.GetDecimal(ordinal);
- default:
- return ReflectionTools.ChangeType<Decimal>(reader.GetValue(ordinal));
- }
- }
-
- public Decimal? GetNullableDecimal(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetDecimal(ordinal);
- }
-
-
- public Int16 GetInt16(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return (Int16)reader.GetByte(ordinal);
- case TypeCode.Int16:
- return reader.GetInt16(ordinal);
- case TypeCode.Int32:
- return (Int16)reader.GetInt32(ordinal);
- case TypeCode.Int64:
- return (Int16)reader.GetInt64(ordinal);
- case TypeCode.Double:
- return (Int16)reader.GetDouble(ordinal);
- case TypeCode.Single:
- return (Int16)reader.GetFloat(ordinal);
- case TypeCode.Decimal:
- return (Int16)reader.GetDecimal(ordinal);
- default:
- return ReflectionTools.ChangeType<Int16>(reader.GetValue(ordinal));
- }
- }
-
- public Int16? GetNullableInt16(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetInt16(ordinal);
- }
-
-
- public Int32 GetInt32(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return (Int32)reader.GetByte(ordinal);
- case TypeCode.Int16:
- return (Int32)reader.GetInt16(ordinal);
- case TypeCode.Int32:
- return reader.GetInt32(ordinal);
- case TypeCode.Int64:
- return (Int32)reader.GetInt64(ordinal);
- case TypeCode.Double:
- return (Int32)reader.GetDouble(ordinal);
- case TypeCode.Single:
- return (Int32)reader.GetFloat(ordinal);
- case TypeCode.Decimal:
- return (Int32)reader.GetDecimal(ordinal);
- default:
- return ReflectionTools.ChangeType<Int32>(reader.GetValue(ordinal));
- }
- }
-
- public Int32? GetNullableInt32(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetInt32(ordinal);
- }
-
-
- public Int64 GetInt64(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case TypeCode.Byte:
- return (Int64)reader.GetByte(ordinal);
- case TypeCode.Int16:
- return (Int64)reader.GetInt16(ordinal);
- case TypeCode.Int32:
- return (Int64)reader.GetInt32(ordinal);
- case TypeCode.Int64:
- return (Int64)reader.GetInt64(ordinal);
- case TypeCode.Double:
- return (Int64)reader.GetDouble(ordinal);
- case TypeCode.Single:
- return (Int64)reader.GetFloat(ordinal);
- case TypeCode.Decimal:
- return (Int64)reader.GetDecimal(ordinal);
- default:
- return ReflectionTools.ChangeType<Int64>(reader.GetValue(ordinal));
- }
- }
-
- public Int64? GetNullableInt64(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetInt64(ordinal);
- }
-
-
- public DateTime GetDateTime(int ordinal)
- {
- LastOrdinal = ordinal;
- DateTime dt;
- switch (typeCodes[ordinal])
- {
- case TypeCode.DateTime:
- dt = reader.GetDateTime(ordinal);
- break;
- default:
- dt = ReflectionTools.ChangeType<DateTime>(reader.GetValue(ordinal));
- break;
- }
-
- if (Schema.Current.TimeZoneMode == TimeZoneMode.Utc)
- return new DateTime(dt.Ticks, DateTimeKind.Utc);
- return dt;
- }
-
- public DateTime? GetNullableDateTime(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetDateTime(ordinal);
- }
-
-
- public DateTimeOffset GetDateTimeOffset(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case tcDateTimeOffset:
- return ((SqlDataReader)reader).GetDateTimeOffset(ordinal);
- default:
- return ReflectionTools.ChangeType<DateTimeOffset>(reader.GetValue(ordinal));
- }
- }
-
- public DateTimeOffset? GetNullableDateTimeOffset(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetDateTimeOffset(ordinal);
- }
-
-
- public TimeSpan GetTimeSpan(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case tcTimeSpan:
- return ((SqlDataReader)reader).GetTimeSpan(ordinal);
- default:
- return ReflectionTools.ChangeType<TimeSpan>(reader.GetValue(ordinal));
- }
- }
-
- public TimeSpan? GetNullableTimeSpan(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetTimeSpan(ordinal);
- }
-
-
- public Guid GetGuid(int ordinal)
- {
- LastOrdinal = ordinal;
- switch (typeCodes[ordinal])
- {
- case tcGuid:
- return reader.GetGuid(ordinal);
- default:
- return ReflectionTools.ChangeType<Guid>(reader.GetValue(ordinal));
- }
- }
-
- public Guid? GetNullableGuid(int ordinal)
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return null;
- }
- return GetGuid(ordinal);
- }
-
- static MethodInfo miGetUdt = ReflectionTools.GetMethodInfo((FieldReader r) => r.GetUdt<IBinarySerialize>(0)).GetGenericMethodDefinition();
-
- public T GetUdt<T>(int ordinal) where T : IBinarySerialize
- {
- LastOrdinal = ordinal;
- if (reader.IsDBNull(ordinal))
- {
- return (T)(object)null;
- }
- return (T)reader.GetValue(ordinal);
- }
-
- static Dictionary<Type, MethodInfo> methods =
- typeof(FieldReader).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
- .Where(m => m.Name != "GetExpression" && m.Name != "IsNull")
- .ToDictionary(a => a.ReturnType);
-
-
- public static Expression GetExpression(Expression reader, int ordinal, Type type)
- {
- MethodInfo mi = methods.TryGetC(type);
-
- if (mi != null)
- return Expression.Call(reader, mi, Expression.Constant(ordinal));
-
- if (typeof(IBinarySerialize).IsAssignableFrom(type.UnNullify()))
- {
- if (type.IsNullable())
- return Expression.Call(reader, miGetUdt.MakeGenericMethod(type.UnNullify()), Expression.Constant(ordinal)).Nullify();
- else
- return Expression.Call(reader, miGetUdt.MakeGenericMethod(type.UnNullify()), Expression.Constant(ordinal));
- }
-
- throw new InvalidOperationException("Type {0} not supported".Formato(type));
- }
-
- static MethodInfo miIsNull = ReflectionTools.GetMethodInfo((FieldReader r) => r.IsNull(0));
-
- public static Expression GetIsNull(Expression reader, int ordinal)
- {
- return Expression.Call(reader, miIsNull, Expression.Constant(ordinal));
- }
-
- internal FieldReaderException CreateFieldReaderException(Exception ex)
- {
- return new FieldReaderException(ex)
- {
- Ordinal = LastOrdinal,
- ColumnName = reader.GetName(LastOrdinal),
- ColumnType = reader.GetFieldType(LastOrdinal),
- };
- }
- }
-
- [Serializable]
- public class FieldReaderException : SqlTypeException
- {
- public FieldReaderException(Exception inner) : base(null, inner) { }
- protected FieldReaderException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context)
- : base(info, context) { }
-
- public override string Message
- {
- get
- {
- string text = "{0}\r\nOrdinal: {1}\r\nColumnName: {2}\r\nRow: {3}".Formato(
- InnerException.Message, Ordinal, ColumnName, Row);
-
- if (Projector != null)
- {
- text += "\r\nCalling: row.Reader.Get{0}({1})".Formato(ColumnType.Name, Ordinal);
- text += "\r\nProjector:\r\n{0}".Formato(Projector.NiceToString().Indent(4));
- }
-
- if(Command != null)
- text += "\r\nCommand:\r\n{0}".Formato(Command.PlainSql().Indent(4));
-
- return text;
- }
- }
-
- public int Ordinal { get; internal set; }
- public string ColumnName { get; internal set; }
- public Type ColumnType { get; internal set; }
- public int Row { get; internal set; }
- public SqlPreCommand Command { get; internal set; }
- public LambdaExpression Projector { get; internal set; }
- }
- }