Commit 3be5fd77 authored by mgravell's avatar mgravell

c# 3.0 / .NET 3.5 support

parent 19af49f2
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B26305D8-3A89-4D68-A981-9BBF378B81FA}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dapper_NET35</RootNamespace>
<AssemblyName>Dapper NET35</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;CSHARP30</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;CSHARP30</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>3</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Dapper\Properties\AssemblyInfo.cs">
<Link>AssemblyInfo.cs</Link>
</Compile>
<Compile Include="..\Dapper\SqlMapper.cs">
<Link>SqlMapper.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
...@@ -5,6 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper", "Dapper\Dapper.csp ...@@ -5,6 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper", "Dapper\Dapper.csp
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DapperTests", "Tests\DapperTests.csproj", "{A2A80512-11F4-4028-A995-505463632C84}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DapperTests", "Tests\DapperTests.csproj", "{A2A80512-11F4-4028-A995-505463632C84}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper NET35", "Dapper NET35\Dapper NET35.csproj", "{B26305D8-3A89-4D68-A981-9BBF378B81FA}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
...@@ -35,6 +37,16 @@ Global ...@@ -35,6 +37,16 @@ Global
{A2A80512-11F4-4028-A995-505463632C84}.Release|Mixed Platforms.Build.0 = Release|x86 {A2A80512-11F4-4028-A995-505463632C84}.Release|Mixed Platforms.Build.0 = Release|x86
{A2A80512-11F4-4028-A995-505463632C84}.Release|x86.ActiveCfg = Release|x86 {A2A80512-11F4-4028-A995-505463632C84}.Release|x86.ActiveCfg = Release|x86
{A2A80512-11F4-4028-A995-505463632C84}.Release|x86.Build.0 = Release|x86 {A2A80512-11F4-4028-A995-505463632C84}.Release|x86.Build.0 = Release|x86
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Debug|x86.ActiveCfg = Debug|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Release|Any CPU.Build.0 = Release|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{B26305D8-3A89-4D68-A981-9BBF378B81FA}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
......
/* /*
License: http://www.apache.org/licenses/LICENSE-2.0 License: http://www.apache.org/licenses/LICENSE-2.0
Home page: http://code.google.com/p/dapper-dot-net/ Home page: http://code.google.com/p/dapper-dot-net/
*/
Note: to build on C# 3.0 + .NET 3.5, include the CSHARP30 compiler symbol (and yes,
I know the difference between language and runtime versions; this is a compromise).
*/
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Data; using System.Data;
using System.Dynamic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Emit; using System.Reflection.Emit;
using System.ComponentModel; using System.Text;
namespace Dapper namespace Dapper
{ {
...@@ -29,8 +30,44 @@ class CacheInfo ...@@ -29,8 +30,44 @@ class CacheInfo
public object[] OtherDeserializers { get; set; } public object[] OtherDeserializers { get; set; }
public Action<IDbCommand, object> ParamReader { get; set; } public Action<IDbCommand, object> ParamReader { get; set; }
} }
#if CSHARP30
static readonly ConcurrentDictionary<Identity, CacheInfo> queryCache = new ConcurrentDictionary<Identity, CacheInfo>(); private static readonly System.Threading.ReaderWriterLockSlim queryLock = new System.Threading.ReaderWriterLockSlim();
private static readonly Dictionary<Identity, CacheInfo> _queryCache = new Dictionary<Identity, CacheInfo>();
private static void SetQueryCache(Identity key, CacheInfo value)
{
queryLock.EnterWriteLock();
try
{
_queryCache[key] = value;
}
finally
{
queryLock.ExitWriteLock();
}
}
private static bool TryGetQueryCache(Identity key, out CacheInfo value)
{
queryLock.EnterReadLock();
try
{
return _queryCache.TryGetValue(key, out value);
}
finally
{
queryLock.ExitReadLock();
}
}
#else
static readonly System.Collections.Concurrent.ConcurrentDictionary<Identity, CacheInfo> _queryCache = new System.Collections.Concurrent.ConcurrentDictionary<Identity, CacheInfo>();
private static void SetQueryCache(Identity key, CacheInfo value)
{
_queryCache[key] = value;
}
private static bool TryGetQueryCache(Identity key, out CacheInfo value)
{
return _queryCache.TryGetValue(key, out value);
}
#endif
static readonly Dictionary<RuntimeTypeHandle, DbType> typeMap; static readonly Dictionary<RuntimeTypeHandle, DbType> typeMap;
static SqlMapper() static SqlMapper()
...@@ -91,7 +128,7 @@ private static DbType LookupDbType(Type type) ...@@ -91,7 +128,7 @@ private static DbType LookupDbType(Type type)
private class Identity : IEquatable<Identity> private class Identity : IEquatable<Identity>
{ {
internal Identity(string sql, IDbConnection cnn, Type type, Type parametersType, Type[] otherTypes = null) internal Identity(string sql, IDbConnection cnn, Type type, Type parametersType, Type[] otherTypes)
{ {
this.sql = sql; this.sql = sql;
this.connectionString = cnn.ConnectionString; this.connectionString = cnn.ConnectionString;
...@@ -141,13 +178,19 @@ public bool Equals(Identity other) ...@@ -141,13 +178,19 @@ public bool Equals(Identity other)
/// Execute parameterized SQL /// Execute parameterized SQL
/// </summary> /// </summary>
/// <returns>Number of rows affected</returns> /// <returns>Number of rows affected</returns>
public static int Execute(this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) public static int Execute(
{ #if CSHARP30
var identity = new Identity(sql, cnn, null, param == null ? null : param.GetType()); this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif
)
{
var identity = new Identity(sql, cnn, null, param == null ? null : param.GetType(), null);
var info = GetCacheInfo(param, identity); var info = GetCacheInfo(param, identity);
return ExecuteCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout, commandType); return ExecuteCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout, commandType);
} }
#if !CSHARP30
/// <summary> /// <summary>
/// Return a list of dynamic objects, reader is closed after the call /// Return a list of dynamic objects, reader is closed after the call
/// </summary> /// </summary>
...@@ -155,10 +198,16 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -155,10 +198,16 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
{ {
return Query<FastExpando>(cnn, sql, param as object, transaction, buffered, commandTimeout, commandType); return Query<FastExpando>(cnn, sql, param as object, transaction, buffered, commandTimeout, commandType);
} }
#endif
// the dynamic param may seem a bit odd, but this works around a major usability issue in vs, if it is Object vs completion gets annoying. Eg type new <space> get new object // the dynamic param may seem a bit odd, but this works around a major usability issue in vs, if it is Object vs completion gets annoying. Eg type new <space> get new object
public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null) public static IEnumerable<T> Query<T>(
#if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType
#else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null
#endif
)
{ {
var data = QueryInternal<T>(cnn, sql, param as object, transaction, commandTimeout, commandType); var data = QueryInternal<T>(cnn, sql, param as object, transaction, commandTimeout, commandType);
return buffered ? data.ToList() : data; return buffered ? data.ToList() : data;
...@@ -167,9 +216,16 @@ public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, dynami ...@@ -167,9 +216,16 @@ public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, dynami
/// <summary> /// <summary>
/// Execute a command that returns multiple result sets, and access each in turn /// Execute a command that returns multiple result sets, and access each in turn
/// </summary> /// </summary>
public static GridReader QueryMultiple(this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) public static GridReader QueryMultiple(
#if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif
)
{ {
var identity = new Identity(sql, cnn, typeof(GridReader), param == null ? null : param.GetType()); var identity = new Identity(sql, cnn, typeof(GridReader), param == null ? null : param.GetType(), null);
var info = GetCacheInfo(param, identity); var info = GetCacheInfo(param, identity);
IDbCommand cmd = null; IDbCommand cmd = null;
...@@ -191,9 +247,9 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, dynam ...@@ -191,9 +247,9 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, dynam
/// <summary> /// <summary>
/// Return a typed list of objects, reader is closed after the call /// Return a typed list of objects, reader is closed after the call
/// </summary> /// </summary>
private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType)
{ {
var identity = new Identity(sql, cnn, typeof(T), param == null ? null : param.GetType()); var identity = new Identity(sql, cnn, typeof(T), param == null ? null : param.GetType(), null);
var info = GetCacheInfo(param, identity); var info = GetCacheInfo(param, identity);
using (var cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout, commandType)) using (var cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout, commandType))
...@@ -202,8 +258,8 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -202,8 +258,8 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
{ {
if (info.Deserializer == null) if (info.Deserializer == null)
{ {
info.Deserializer = GetDeserializer<T>(reader); info.Deserializer = GetDeserializer<T>(reader, 0, -1, false);
queryCache[identity] = info; SetQueryCache(identity, info);
} }
var deserializer = (Func<IDataReader, T>)info.Deserializer; var deserializer = (Func<IDataReader, T>)info.Deserializer;
...@@ -230,36 +286,55 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -230,36 +286,55 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
/// <param name="splitOn">The Field we should split and read the second object from (default: id)</param> /// <param name="splitOn">The Field we should split and read the second object from (default: id)</param>
/// <param name="commandTimeout">Number of seconds before command execution timeout</param> /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
/// <returns></returns> /// <returns></returns>
public static IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) public static IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(
#if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif
)
{ {
return MultiMap<TFirst, TSecond, DontMap, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, DontMap, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(
#if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif
)
{ {
return MultiMap<TFirst, TSecond, TThird, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(
#if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif
)
{ {
return MultiMap<TFirst, TSecond, TThird, TFourth, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, TFourth, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
#if !CSHARP30
public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
{ {
return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
#endif
class DontMap {} class DontMap {}
static IEnumerable<TReturn> MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, string sql, object map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) static IEnumerable<TReturn> MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(
this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType)
{ {
var results = MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, sql, map, param, transaction, splitOn, commandTimeout, commandType); var results = MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, sql, map, param, transaction, splitOn, commandTimeout, commandType);
return buffered ? results.ToList() : results; return buffered ? results.ToList() : results;
} }
static IEnumerable<TReturn> MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, string sql, object map, object param = null, IDbTransaction transaction = null, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) static IEnumerable<TReturn> MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, string splitOn, int? commandTimeout, CommandType? commandType)
{ {
var identity = new Identity(sql, cnn, typeof(TFirst), param == null ? null : param.GetType(), otherTypes: new[] { typeof(TFirst), typeof(TSecond), typeof(TThird), typeof(TFourth), typeof(TFifth) }); var identity = new Identity(sql, cnn, typeof(TFirst), param == null ? null : param.GetType(), new[] { typeof(TFirst), typeof(TSecond), typeof(TThird), typeof(TFourth), typeof(TFifth) });
var info = GetCacheInfo(param, identity); var info = GetCacheInfo(param, identity);
using (var cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout, commandType)) using (var cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout, commandType))
...@@ -288,35 +363,35 @@ class DontMap {} ...@@ -288,35 +363,35 @@ class DontMap {}
var otherDeserializer = new List<object>(); var otherDeserializer = new List<object>();
int split = nextSplit(); int split = nextSplit();
info.Deserializer = GetDeserializer<TFirst>(reader, 0, split); info.Deserializer = GetDeserializer<TFirst>(reader, 0, split, false);
if (typeof(TSecond) != typeof(DontMap)) if (typeof(TSecond) != typeof(DontMap))
{ {
var next = nextSplit(); var next = nextSplit();
otherDeserializer.Add(GetDeserializer<TSecond>(reader, split, next - split, returnNullIfFirstMissing: true)); otherDeserializer.Add(GetDeserializer<TSecond>(reader, split, next - split, true));
split = next; split = next;
} }
if (typeof(TThird) != typeof(DontMap)) if (typeof(TThird) != typeof(DontMap))
{ {
var next = nextSplit(); var next = nextSplit();
otherDeserializer.Add(GetDeserializer<TThird>(reader, split, next - split, returnNullIfFirstMissing: true)); otherDeserializer.Add(GetDeserializer<TThird>(reader, split, next - split, true));
split = next; split = next;
} }
if (typeof(TFourth) != typeof(DontMap)) if (typeof(TFourth) != typeof(DontMap))
{ {
var next = nextSplit(); var next = nextSplit();
otherDeserializer.Add(GetDeserializer<TFourth>(reader, split, next - split, returnNullIfFirstMissing: true)); otherDeserializer.Add(GetDeserializer<TFourth>(reader, split, next - split, true));
split = next; split = next;
} }
if (typeof(TFifth) != typeof(DontMap)) if (typeof(TFifth) != typeof(DontMap))
{ {
var next = nextSplit(); var next = nextSplit();
otherDeserializer.Add(GetDeserializer<TFifth>(reader, split, next - split, returnNullIfFirstMissing: true)); otherDeserializer.Add(GetDeserializer<TFifth>(reader, split, next - split, true));
} }
info.OtherDeserializers = otherDeserializer.ToArray(); info.OtherDeserializers = otherDeserializer.ToArray();
queryCache[identity] = info; SetQueryCache(identity, info);
} }
var deserializer = (Func<IDataReader, TFirst>)info.Deserializer; var deserializer = (Func<IDataReader, TFirst>)info.Deserializer;
...@@ -348,8 +423,12 @@ class DontMap {} ...@@ -348,8 +423,12 @@ class DontMap {}
if (info.OtherDeserializers.Length > 3) if (info.OtherDeserializers.Length > 3)
{ {
#if CSHARP30
throw new NotSupportedException();
#else
var deserializer5 = (Func<IDataReader, TFifth>)info.OtherDeserializers[3]; var deserializer5 = (Func<IDataReader, TFifth>)info.OtherDeserializers[3];
mapIt = r => ((Func<TFirst, TSecond, TThird, TFourth,TFifth,TReturn>)map)(deserializer(r), deserializer2(r), deserializer3(r), deserializer4(r),deserializer5(r)); mapIt = r => ((Func<TFirst, TSecond, TThird, TFourth,TFifth,TReturn>)map)(deserializer(r), deserializer2(r), deserializer3(r), deserializer4(r),deserializer5(r));
#endif
} }
} }
} }
...@@ -366,7 +445,7 @@ class DontMap {} ...@@ -366,7 +445,7 @@ class DontMap {}
private static CacheInfo GetCacheInfo(object param, Identity identity) private static CacheInfo GetCacheInfo(object param, Identity identity)
{ {
CacheInfo info; CacheInfo info;
if (!queryCache.TryGetValue(identity, out info)) if (!TryGetQueryCache(identity, out info))
{ {
info = new CacheInfo(); info = new CacheInfo();
if (param != null) if (param != null)
...@@ -384,13 +463,16 @@ private static CacheInfo GetCacheInfo(object param, Identity identity) ...@@ -384,13 +463,16 @@ private static CacheInfo GetCacheInfo(object param, Identity identity)
return info; return info;
} }
private static Func<IDataReader, T> GetDeserializer<T>(IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) private static Func<IDataReader, T> GetDeserializer<T>(IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing)
{ {
#if !CSHARP30
// dynamic is passed in as Object ... by c# design // dynamic is passed in as Object ... by c# design
if (typeof (T) == typeof (object) || typeof (T) == typeof (FastExpando)) if (typeof (T) == typeof (object)
|| typeof (T) == typeof (FastExpando))
{ {
return GetDynamicDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing); return GetDynamicDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing);
} }
#endif
if (typeof (T).IsClass && typeof (T) != typeof (string)) if (typeof (T).IsClass && typeof (T) != typeof (string))
{ {
return GetClassDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing); return GetClassDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing);
...@@ -398,8 +480,8 @@ private static CacheInfo GetCacheInfo(object param, Identity identity) ...@@ -398,8 +480,8 @@ private static CacheInfo GetCacheInfo(object param, Identity identity)
return GetStructDeserializer<T>(); return GetStructDeserializer<T>();
} }
#if !CSHARP30
private class FastExpando : DynamicObject private class FastExpando : System.Dynamic.DynamicObject
{ {
IDictionary<string, object> data; IDictionary<string, object> data;
...@@ -408,19 +490,20 @@ public static FastExpando Attach(IDictionary<string, object> data) ...@@ -408,19 +490,20 @@ public static FastExpando Attach(IDictionary<string, object> data)
return new FastExpando {data = data}; return new FastExpando {data = data};
} }
public override bool TrySetMember(SetMemberBinder binder, object value) public override bool TrySetMember(System.Dynamic.SetMemberBinder binder, object value)
{ {
data[binder.Name] = value; data[binder.Name] = value;
return true; return true;
} }
public override bool TryGetMember(GetMemberBinder binder, out object result) public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
{ {
return data.TryGetValue(binder.Name, out result); return data.TryGetValue(binder.Name, out result);
} }
} }
private static Func<IDataReader, T> GetDynamicDeserializer<T>(IDataRecord reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false)
private static Func<IDataReader, T> GetDynamicDeserializer<T>(IDataRecord reader, int startBound, int length, bool returnNullIfFirstMissing)
{ {
if (length == -1) if (length == -1)
{ {
...@@ -444,8 +527,8 @@ public override bool TryGetMember(GetMemberBinder binder, out object result) ...@@ -444,8 +527,8 @@ public override bool TryGetMember(GetMemberBinder binder, out object result)
//we know this is an object so it will not box //we know this is an object so it will not box
return (T)(object)FastExpando.Attach(row); return (T)(object)FastExpando.Attach(row);
}; };
} }
#endif
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("This method is for internal usage only", true)] [Obsolete("This method is for internal usage only", true)]
public static void PackListParameters(IDbCommand command, string namePrefix, object value) public static void PackListParameters(IDbCommand command, string namePrefix, object value)
...@@ -482,10 +565,13 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj ...@@ -482,10 +565,13 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
} }
else else
{ {
command.CommandText = command.CommandText.Replace(namePrefix, var sb = new StringBuilder("(").Append(namePrefix).Append(1);
"(" + string.Join( for (int i = 2; i <= count; i++)
",", Enumerable.Range(1, count).Select(i => namePrefix + i.ToString()) {
) + ")"); sb.Append(',').Append(namePrefix).Append(i);
}
string inQuery = sb.Append(')').ToString();
command.CommandText = command.CommandText.Replace(namePrefix, inQuery);
} }
} }
...@@ -659,7 +745,13 @@ private static int ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction, ...@@ -659,7 +745,13 @@ private static int ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction,
}; };
} }
public static Func<IDataReader, T> GetClassDeserializer<T>(IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) public static Func<IDataReader, T> GetClassDeserializer<T>(
#if CSHARP30
IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing
#else
IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false
#endif
)
{ {
var dm = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), typeof(T), new[] { typeof(IDataReader) }, true); var dm = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), typeof(T), new[] { typeof(IDataReader) }, true);
...@@ -833,7 +925,7 @@ public IEnumerable<T> Read<T>() ...@@ -833,7 +925,7 @@ public IEnumerable<T> Read<T>()
{ {
if (reader == null) throw new ObjectDisposedException(GetType().Name); if (reader == null) throw new ObjectDisposedException(GetType().Name);
if (consumed) throw new InvalidOperationException("Each grid can only be iterated once"); if (consumed) throw new InvalidOperationException("Each grid can only be iterated once");
var deserializer = GetDeserializer<T>(reader); var deserializer = GetDeserializer<T>(reader, 0, -1, false);
consumed = true; consumed = true;
return ReadDeferred(gridIndex, deserializer); return ReadDeferred(gridIndex, deserializer);
} }
...@@ -902,7 +994,13 @@ class ParamInfo ...@@ -902,7 +994,13 @@ class ParamInfo
} }
public void Add(string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null) public void Add(
#if CSHARP30
string name, object value, DbType? dbType, ParameterDirection? direction, int? size
#else
string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null
#endif
)
{ {
parameters[name] = new ParamInfo() { Name = name, Value = value, ParameterDirection = direction ?? ParameterDirection.Input, DbType = dbType, Size = size }; parameters[name] = new ParamInfo() { Name = name, Value = value, ParameterDirection = direction ?? ParameterDirection.Input, DbType = dbType, Size = size };
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment