提交 0add8271 编写于 作者: S Sam Saffron

Merge with simon

......@@ -8,6 +8,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Dynamic;
using System.Linq;
using System.Reflection;
......@@ -31,51 +32,51 @@ class CacheInfo
}
static readonly ConcurrentDictionary<Identity, CacheInfo> queryCache = new ConcurrentDictionary<Identity, CacheInfo>();
static readonly Dictionary<Type, DbType> typeMap;
static readonly Dictionary<RuntimeTypeHandle, DbType> typeMap;
static SqlMapper()
{
typeMap = new Dictionary<Type, DbType>();
typeMap[typeof(byte)] = DbType.Byte;
typeMap[typeof(sbyte)] = DbType.SByte;
typeMap[typeof(short)] = DbType.Int16;
typeMap[typeof(ushort)] = DbType.UInt16;
typeMap[typeof(int)] = DbType.Int32;
typeMap[typeof(uint)] = DbType.UInt32;
typeMap[typeof(long)] = DbType.Int64;
typeMap[typeof(ulong)] = DbType.UInt64;
typeMap[typeof(float)] = DbType.Single;
typeMap[typeof(double)] = DbType.Double;
typeMap[typeof(decimal)] = DbType.Decimal;
typeMap[typeof(bool)] = DbType.Boolean;
typeMap[typeof(string)] = DbType.String;
typeMap[typeof(char)] = DbType.StringFixedLength;
typeMap[typeof(Guid)] = DbType.Guid;
typeMap[typeof(DateTime)] = DbType.DateTime;
typeMap[typeof(DateTimeOffset)] = DbType.DateTimeOffset;
typeMap[typeof(byte[])] = DbType.Binary;
typeMap[typeof(byte?)] = DbType.Byte;
typeMap[typeof(sbyte?)] = DbType.SByte;
typeMap[typeof(short?)] = DbType.Int16;
typeMap[typeof(ushort?)] = DbType.UInt16;
typeMap[typeof(int?)] = DbType.Int32;
typeMap[typeof(uint?)] = DbType.UInt32;
typeMap[typeof(long?)] = DbType.Int64;
typeMap[typeof(ulong?)] = DbType.UInt64;
typeMap[typeof(float?)] = DbType.Single;
typeMap[typeof(double?)] = DbType.Double;
typeMap[typeof(decimal?)] = DbType.Decimal;
typeMap[typeof(bool?)] = DbType.Boolean;
typeMap[typeof(char?)] = DbType.StringFixedLength;
typeMap[typeof(Guid?)] = DbType.Guid;
typeMap[typeof(DateTime?)] = DbType.DateTime;
typeMap[typeof(DateTimeOffset?)] = DbType.DateTimeOffset;
typeMap = new Dictionary<RuntimeTypeHandle, DbType>();
typeMap[typeof(byte).TypeHandle] = DbType.Byte;
typeMap[typeof(sbyte).TypeHandle] = DbType.SByte;
typeMap[typeof(short).TypeHandle] = DbType.Int16;
typeMap[typeof(ushort).TypeHandle] = DbType.UInt16;
typeMap[typeof(int).TypeHandle] = DbType.Int32;
typeMap[typeof(uint).TypeHandle] = DbType.UInt32;
typeMap[typeof(long).TypeHandle] = DbType.Int64;
typeMap[typeof(ulong).TypeHandle] = DbType.UInt64;
typeMap[typeof(float).TypeHandle] = DbType.Single;
typeMap[typeof(double).TypeHandle] = DbType.Double;
typeMap[typeof(decimal).TypeHandle] = DbType.Decimal;
typeMap[typeof(bool).TypeHandle] = DbType.Boolean;
typeMap[typeof(string).TypeHandle] = DbType.String;
typeMap[typeof(char).TypeHandle] = DbType.StringFixedLength;
typeMap[typeof(Guid).TypeHandle] = DbType.Guid;
typeMap[typeof(DateTime).TypeHandle] = DbType.DateTime;
typeMap[typeof(DateTimeOffset).TypeHandle] = DbType.DateTimeOffset;
typeMap[typeof(byte[]).TypeHandle] = DbType.Binary;
typeMap[typeof(byte?).TypeHandle] = DbType.Byte;
typeMap[typeof(sbyte?).TypeHandle] = DbType.SByte;
typeMap[typeof(short?).TypeHandle] = DbType.Int16;
typeMap[typeof(ushort?).TypeHandle] = DbType.UInt16;
typeMap[typeof(int?).TypeHandle] = DbType.Int32;
typeMap[typeof(uint?).TypeHandle] = DbType.UInt32;
typeMap[typeof(long?).TypeHandle] = DbType.Int64;
typeMap[typeof(ulong?).TypeHandle] = DbType.UInt64;
typeMap[typeof(float?).TypeHandle] = DbType.Single;
typeMap[typeof(double?).TypeHandle] = DbType.Double;
typeMap[typeof(decimal?).TypeHandle] = DbType.Decimal;
typeMap[typeof(bool?).TypeHandle] = DbType.Boolean;
typeMap[typeof(char?).TypeHandle] = DbType.StringFixedLength;
typeMap[typeof(Guid?).TypeHandle] = DbType.Guid;
typeMap[typeof(DateTime?).TypeHandle] = DbType.DateTime;
typeMap[typeof(DateTimeOffset?).TypeHandle] = DbType.DateTimeOffset;
}
private static DbType LookupDbType(Type type)
{
DbType dbType;
if (typeMap.TryGetValue(type, out dbType))
if (typeMap.TryGetValue(type.TypeHandle, out dbType))
{
return dbType;
}
......@@ -91,17 +92,12 @@ private static DbType LookupDbType(Type type)
private class Identity : IEquatable<Identity>
{
public String ConnectionString { get { return connectionString; } }
public Type Type { get { return type; } }
public string Sql { get { return sql; } }
public Type ParametersType { get { return ParametersType; } }
internal Identity(string sql, IDbConnection cnn, Type type, Type parametersType, Type[] otherTypes = null)
{
this.sql = sql;
this.connectionString = cnn.ConnectionString;
this.type = type;
this.parametersType = parametersType;
this.otherTypes = otherTypes;
unchecked
{
hashCode = 17; // we *know* we are using this in a dictionary, so pre-compute this
......@@ -125,7 +121,6 @@ public override bool Equals(object obj)
private readonly string sql;
private readonly int hashCode;
private readonly Type type;
private readonly Type[] otherTypes;
private readonly string connectionString;
private readonly Type parametersType;
public override int GetHashCode()
......@@ -184,7 +179,7 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, dynam
{
cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout);
reader = cmd.ExecuteReader();
return new GridReader(cmd, reader, cnn, sql);
return new GridReader(cmd, reader);
}
catch
{
......@@ -208,7 +203,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
{
if (info.Deserializer == null)
{
info.Deserializer = GetDeserializer<T>(identity, reader);
info.Deserializer = GetDeserializer<T>(reader);
queryCache[identity] = info;
}
......@@ -274,7 +269,6 @@ class DontMap {}
{
if (info.Deserializer == null)
{
var split = 0;
int current = 0;
Func<int> nextSplit = () =>
......@@ -294,31 +288,31 @@ class DontMap {}
var otherDeserializer = new List<object>();
split = nextSplit();
info.Deserializer = GetDeserializer<TFirst>(identity, reader, 0, split);
int split = nextSplit();
info.Deserializer = GetDeserializer<TFirst>(reader, 0, split);
if (typeof(TSecond) != typeof(DontMap))
{
var next = nextSplit();
otherDeserializer.Add(GetDeserializer<TSecond>(identity, reader, split, next - split, returnNullIfFirstMissing: true));
otherDeserializer.Add(GetDeserializer<TSecond>(reader, split, next - split, returnNullIfFirstMissing: true));
split = next;
}
if (typeof(TThird) != typeof(DontMap))
{
var next = nextSplit();
otherDeserializer.Add(GetDeserializer<TThird>(identity, reader, split, next - split, returnNullIfFirstMissing: true));
otherDeserializer.Add(GetDeserializer<TThird>(reader, split, next - split, returnNullIfFirstMissing: true));
split = next;
}
if (typeof(TFourth) != typeof(DontMap))
{
var next = nextSplit();
otherDeserializer.Add(GetDeserializer<TFourth>(identity, reader, split, next - split, returnNullIfFirstMissing: true));
otherDeserializer.Add(GetDeserializer<TFourth>(reader, split, next - split, returnNullIfFirstMissing: true));
split = next;
}
if (typeof(TFifth) != typeof(DontMap))
{
var next = nextSplit();
otherDeserializer.Add(GetDeserializer<TFifth>(identity, reader, split, next - split, returnNullIfFirstMissing: true));
otherDeserializer.Add(GetDeserializer<TFifth>(reader, split, next - split, returnNullIfFirstMissing: true));
}
info.OtherDeserializers = otherDeserializer.ToArray();
......@@ -391,26 +385,19 @@ private static CacheInfo GetCacheInfo(object param, Identity identity)
return info;
}
private static Func<IDataReader, T> GetDeserializer<T>(Identity identity, IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false)
private static Func<IDataReader, T> GetDeserializer<T>(IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false)
{
object oDeserializer;
// dynamic is passed in as Object ... by c# design
if (typeof(T) == typeof(object) || typeof(T) == typeof(FastExpando))
{
oDeserializer = GetDynamicDeserializer(reader,startBound, length, returnNullIfFirstMissing);
}
else if (typeof(T).IsClass && typeof(T) != typeof(string))
if (typeof (T) == typeof (object) || typeof (T) == typeof (FastExpando))
{
oDeserializer = GetClassDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing: returnNullIfFirstMissing);
return GetDynamicDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing);
}
else
if (typeof (T).IsClass && typeof (T) != typeof (string))
{
oDeserializer = GetStructDeserializer<T>(reader);
return GetClassDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing);
}
return GetStructDeserializer<T>();
var deserializer = (Func<IDataReader, T>)oDeserializer;
return deserializer;
}
private class FastExpando : DynamicObject
......@@ -419,9 +406,7 @@ private class FastExpando : DynamicObject
public static FastExpando Attach(IDictionary<string, object> data)
{
FastExpando expando = new FastExpando();
expando.data = data;
return expando;
return new FastExpando {data = data};
}
public override bool TrySetMember(SetMemberBinder binder, object value)
......@@ -436,14 +421,14 @@ public override bool TryGetMember(GetMemberBinder binder, out object result)
}
}
private static object GetDynamicDeserializer(IDataRecord reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false)
private static Func<IDataReader, T> GetDynamicDeserializer<T>(IDataRecord reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false)
{
if (length == -1)
{
length = reader.FieldCount - startBound;
}
Func<IDataReader, FastExpando> rval =
return
r =>
{
IDictionary<string, object> row = new Dictionary<string,object>(length);
......@@ -454,13 +439,13 @@ private static object GetDynamicDeserializer(IDataRecord reader, int startBound
row[r.GetName(i)] = tmp;
if (returnNullIfFirstMissing && i == startBound && tmp == null)
{
return null;
return default(T);
}
}
return FastExpando.Attach(row);
//we know this is an object so it will not box
return (T)(object)FastExpando.Attach(row);
};
return rval;
}
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("This method is for internal usage only", true)]
......@@ -471,10 +456,10 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
var list = value as IEnumerable;
var count = 0;
bool isString = value is IEnumerable<string>;
if (list != null)
{
bool isString = value is IEnumerable<string>;
foreach (var item in list)
{
count++;
......@@ -660,11 +645,9 @@ private static int ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction,
}
}
private static object GetStructDeserializer<T>(IDataReader reader)
private static Func<IDataReader, T> GetStructDeserializer<T>()
{
Func<IDataReader, T> deserializer = null;
deserializer = r =>
return r =>
{
var val = r.GetValue(0);
if (val == DBNull.Value)
......@@ -673,7 +656,6 @@ private static object GetStructDeserializer<T>(IDataReader reader)
}
return (T)val;
};
return deserializer;
}
public static Func<IDataReader, T> GetClassDeserializer<T>(IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false)
......@@ -723,7 +705,7 @@ private static object GetStructDeserializer<T>(IDataReader reader)
int index = startBound;
var @try = il.BeginExceptionBlock();
il.BeginExceptionBlock();
// stack is empty
il.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); // stack is now [target]
bool first = true;
......@@ -837,19 +819,10 @@ private static void EmitInt32(ILGenerator il, int value)
public class GridReader : IDisposable
{
private IDataReader reader;
private IDbConnection connection;
private IDbCommand command;
private readonly string sql;
internal GridReader(IDbCommand command, IDataReader reader, IDbConnection connection, string sql)
internal GridReader(IDbCommand command, IDataReader reader)
{
if (reader == null) throw new ArgumentNullException("reader");
if (connection == null) throw new ArgumentNullException("connection");
if (sql == null) throw new ArgumentNullException("sql");
if (command == null) throw new ArgumentNullException("command");
this.sql = sql;
this.command = command;
this.connection = connection;
this.reader = reader;
}
/// <summary>
......@@ -859,8 +832,7 @@ public IEnumerable<T> Read<T>()
{
if (reader == null) throw new ObjectDisposedException(GetType().Name);
if (consumed) throw new InvalidOperationException("Each grid can only be iterated once");
var identity = new Identity(sql, connection, typeof(T), null);
var deserializer = SqlMapper.GetDeserializer<T>(identity, reader);
var deserializer = GetDeserializer<T>(reader);
consumed = true;
return ReadDeferred(gridIndex, deserializer);
}
......@@ -901,7 +873,6 @@ private void NextResult()
}
public void Dispose()
{
connection = null;
if (reader != null)
{
reader.Dispose();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册