Commit 885a8d46 authored by Marc Gravell's avatar Marc Gravell

Provide support for OleDB / anonymous sql parameters

parent 8f017a25
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="NuGet.CommandLine" version="2.0.40001" />
<package id="NuGet.CommandLine" version="2.5.0" /> <package id="NuGet.CommandLine" version="2.5.0" />
<package id="NuGet.CommandLine" version="2.0.40001" />
</packages> </packages>
\ No newline at end of file
...@@ -264,7 +264,7 @@ public static void PurgeQueryCache() ...@@ -264,7 +264,7 @@ public static void PurgeQueryCache()
{ {
lock (_queryCache) lock (_queryCache)
{ {
_queryCache.Clear(); _queryCache.Clear();
} }
OnQueryCachePurged(); OnQueryCachePurged();
} }
...@@ -656,7 +656,7 @@ public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object ...@@ -656,7 +656,7 @@ public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object
/// <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, object param, IDbTransaction transaction) public static GridReader QueryMultiple(this IDbConnection cnn, string sql, object param, IDbTransaction transaction)
{ {
return QueryMultiple(cnn, sql, param, transaction, null, null); return QueryMultiple(cnn, sql, param, transaction, null, null);
} }
...@@ -664,7 +664,7 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, objec ...@@ -664,7 +664,7 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, objec
/// <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, object param, CommandType commandType) public static GridReader QueryMultiple(this IDbConnection cnn, string sql, object param, CommandType commandType)
{ {
return QueryMultiple(cnn, sql, param, null, null, commandType); return QueryMultiple(cnn, sql, param, null, null, commandType);
} }
...@@ -683,7 +683,7 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, objec ...@@ -683,7 +683,7 @@ public static GridReader QueryMultiple(this IDbConnection cnn, string sql, objec
/// <returns>Number of rows affected</returns> /// <returns>Number of rows affected</returns>
public static int Execute( public static int Execute(
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
...@@ -741,35 +741,40 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -741,35 +741,40 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
/// <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>
public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param) { public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param)
{
return Query(cnn, sql, param, null, true, null, null); return Query(cnn, sql, param, null, true, null, null);
} }
/// <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>
public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param, IDbTransaction transaction) { public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param, IDbTransaction transaction)
{
return Query(cnn, sql, param, transaction, true, null, null); return Query(cnn, sql, param, transaction, true, null, null);
} }
/// <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>
public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param, CommandType? commandType) { public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param, CommandType? commandType)
{
return Query(cnn, sql, param, null, true, null, commandType); return Query(cnn, sql, param, null, true, null, commandType);
} }
/// <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>
public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param, IDbTransaction transaction, CommandType? commandType) { public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param, IDbTransaction transaction, CommandType? commandType)
{
return Query(cnn, sql, param, transaction, true, null, commandType); return Query(cnn, sql, param, transaction, true, null, commandType);
} }
/// <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>
public static IEnumerable<IDictionary<string,object>> Query(this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType) { public static IEnumerable<IDictionary<string, object>> Query(this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType)
{
return Query<IDictionary<string, object>>(cnn, sql, param, transaction, buffered, commandTimeout, commandType); return Query<IDictionary<string, object>>(cnn, sql, param, transaction, buffered, commandTimeout, commandType);
} }
#endif #endif
...@@ -783,7 +788,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -783,7 +788,7 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
/// </returns> /// </returns>
public static IEnumerable<T> Query<T>( public static IEnumerable<T> Query<T>(
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
...@@ -797,8 +802,8 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -797,8 +802,8 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
/// 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( public static GridReader QueryMultiple(
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
...@@ -908,8 +913,8 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -908,8 +913,8 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
/// <param name="commandType">Is it a stored proc or a batch?</param> /// <param name="commandType">Is it a stored proc or a batch?</param>
/// <returns></returns> /// <returns></returns>
public static IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>( public static IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else #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 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 #endif
...@@ -937,7 +942,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -937,7 +942,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
/// <returns></returns> /// <returns></returns>
public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>( public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(
#if CSHARP30 #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 this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else #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 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 #endif
...@@ -966,7 +971,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -966,7 +971,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
/// <returns></returns> /// <returns></returns>
public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>( public static IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(
#if CSHARP30 #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 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 #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 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 #endif
...@@ -1064,7 +1069,7 @@ partial class DontMap { } ...@@ -1064,7 +1069,7 @@ partial class DontMap { }
return buffered ? results.ToList() : results; return buffered ? results.ToList() : results;
} }
static IEnumerable<TReturn> MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, string splitOn, int? commandTimeout, CommandType? commandType, IDataReader reader, Identity identity) static IEnumerable<TReturn> MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, string splitOn, int? commandTimeout, CommandType? commandType, IDataReader reader, Identity identity)
{ {
identity = identity ?? new Identity(sql, commandType, cnn, typeof(TFirst), (object)param == null ? null : ((object)param).GetType(), new[] { typeof(TFirst), typeof(TSecond), typeof(TThird), typeof(TFourth), typeof(TFifth), typeof(TSixth), typeof(TSeventh) }); identity = identity ?? new Identity(sql, commandType, cnn, typeof(TFirst), (object)param == null ? null : ((object)param).GetType(), new[] { typeof(TFirst), typeof(TSecond), typeof(TThird), typeof(TFourth), typeof(TFifth), typeof(TSixth), typeof(TSeventh) });
...@@ -1247,7 +1252,7 @@ private static CacheInfo GetCacheInfo(Identity identity) ...@@ -1247,7 +1252,7 @@ private static CacheInfo GetCacheInfo(Identity identity)
#endif #endif
else else
{ {
info.ParamReader = CreateParamInfoGenerator(identity, false); info.ParamReader = CreateParamInfoGenerator(identity, false, true);
} }
} }
SetQueryCache(identity, info); SetQueryCache(identity, info);
...@@ -1265,7 +1270,7 @@ private static CacheInfo GetCacheInfo(Identity identity) ...@@ -1265,7 +1270,7 @@ private static CacheInfo GetCacheInfo(Identity identity)
return GetDapperRowDeserializer(reader, startBound, length, returnNullIfFirstMissing); return GetDapperRowDeserializer(reader, startBound, length, returnNullIfFirstMissing);
} }
#else #else
if(type.IsAssignableFrom(typeof(Dictionary<string,object>))) if (type.IsAssignableFrom(typeof(Dictionary<string, object>)))
{ {
return GetDictionaryDeserializer(reader, startBound, length, returnNullIfFirstMissing); return GetDictionaryDeserializer(reader, startBound, length, returnNullIfFirstMissing);
} }
...@@ -1497,7 +1502,7 @@ IEnumerator IEnumerable.GetEnumerator() ...@@ -1497,7 +1502,7 @@ IEnumerator IEnumerable.GetEnumerator()
return GetEnumerator(); return GetEnumerator();
} }
#region Implementation of ICollection<KeyValuePair<string,object>> #region Implementation of ICollection<KeyValuePair<string,object>>
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item) void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item)
{ {
...@@ -1538,7 +1543,7 @@ IEnumerator IEnumerable.GetEnumerator() ...@@ -1538,7 +1543,7 @@ IEnumerator IEnumerable.GetEnumerator()
#endregion #endregion
#region Implementation of IDictionary<string,object> #region Implementation of IDictionary<string,object>
bool IDictionary<string, object>.ContainsKey(string key) bool IDictionary<string, object>.ContainsKey(string key)
{ {
...@@ -1831,13 +1836,22 @@ private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyIn ...@@ -1831,13 +1836,22 @@ private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyIn
return parameters.Where(p => Regex.IsMatch(sql, @"[?@:]" + p.Name + "([^a-zA-Z0-9_]+|$)", RegexOptions.IgnoreCase | RegexOptions.Multiline)); return parameters.Where(p => Regex.IsMatch(sql, @"[?@:]" + p.Name + "([^a-zA-Z0-9_]+|$)", RegexOptions.IgnoreCase | RegexOptions.Multiline));
} }
// look for ? / @ / : *by itself*
static readonly Regex smellsLikeOleDb = new Regex(@"(?<![a-zA-Z0-9_])[?@:](?![a-zA-Z0-9_])", RegexOptions.Compiled);
/// <summary> /// <summary>
/// Internal use only /// Internal use only
/// </summary> /// </summary>
public static Action<IDbCommand, object> CreateParamInfoGenerator(Identity identity, bool checkForDuplicates) public static Action<IDbCommand, object> CreateParamInfoGenerator(Identity identity, bool checkForDuplicates, bool removeUnused)
{ {
Type type = identity.parametersType; Type type = identity.parametersType;
bool filterParams = identity.commandType.GetValueOrDefault(CommandType.Text) == CommandType.Text;
bool filterParams = false;
if (removeUnused && identity.commandType.GetValueOrDefault(CommandType.Text) == CommandType.Text)
{
filterParams = !smellsLikeOleDb.IsMatch(identity.sql);
}
var dm = new DynamicMethod(string.Format("ParamInfo{0}", Guid.NewGuid()), null, new[] { typeof(IDbCommand), typeof(object) }, type, true); var dm = new DynamicMethod(string.Format("ParamInfo{0}", Guid.NewGuid()), null, new[] { typeof(IDbCommand), typeof(object) }, type, true);
var il = dm.GetILGenerator(); var il = dm.GetILGenerator();
...@@ -1851,11 +1865,63 @@ private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyIn ...@@ -1851,11 +1865,63 @@ private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyIn
il.Emit(OpCodes.Ldarg_0); // stack is now [command] il.Emit(OpCodes.Ldarg_0); // stack is now [command]
il.EmitCall(OpCodes.Callvirt, typeof(IDbCommand).GetProperty("Parameters").GetGetMethod(), null); // stack is now [parameters] il.EmitCall(OpCodes.Callvirt, typeof(IDbCommand).GetProperty("Parameters").GetGetMethod(), null); // stack is now [parameters]
IEnumerable<PropertyInfo> props = type.GetProperties().Where(p => p.GetIndexParameters().Length == 0).OrderBy(p => p.Name); var propsArr = type.GetProperties().Where(p => p.GetIndexParameters().Length == 0).ToArray();
var ctors = type.GetConstructors();
ParameterInfo[] ctorParams;
IEnumerable<PropertyInfo> props = null;
// try to detect tuple patterns, e.g. anon-types, and use that to choose the order
// otherwise: alphabetical
if (ctors.Length == 1 && propsArr.Length == (ctorParams = ctors[0].GetParameters()).Length)
{
// check if reflection was kind enough to put everything in the right order for us
bool ok = true;
for (int i = 0; i < propsArr.Length; i++)
{
if (!string.Equals(propsArr[i].Name, ctorParams[i].Name, StringComparison.InvariantCultureIgnoreCase))
{
ok = false;
break;
}
}
if(ok)
{
// pre-sorted; the reflection gods have smiled upon us
props = propsArr;
}
else { // might still all be accounted for; check the hard way
var positionByName = new Dictionary<string,int>(StringComparer.InvariantCultureIgnoreCase);
foreach(var param in ctorParams)
{
positionByName[param.Name] = param.Position;
}
if (positionByName.Count == propsArr.Length)
{
int[] positions = new int[propsArr.Length];
ok = true;
for (int i = 0; i < propsArr.Length; i++)
{
int pos;
if (!positionByName.TryGetValue(propsArr[i].Name, out pos))
{
ok = false;
break;
}
positions[i] = pos;
}
if (ok)
{
Array.Sort(positions, propsArr);
props = propsArr;
}
}
}
}
if(props == null) props = propsArr.OrderBy(x => x.Name);
if (filterParams) if (filterParams)
{ {
props = FilterParameters(props, identity.sql); props = FilterParameters(props, identity.sql);
} }
foreach (var prop in props) foreach (var prop in props)
{ {
if (filterParams) if (filterParams)
...@@ -2154,7 +2220,7 @@ public static void SetTypeMap(Type type, ITypeMap map) ...@@ -2154,7 +2220,7 @@ public static void SetTypeMap(Type type, ITypeMap map)
/// <returns></returns> /// <returns></returns>
public static Func<IDataReader, object> GetTypeDeserializer( public static Func<IDataReader, object> GetTypeDeserializer(
#if CSHARP30 #if CSHARP30
Type type, IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing Type type, IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing
#else #else
Type type, IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false Type type, IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false
#endif #endif
...@@ -2489,7 +2555,7 @@ static MethodInfo GetOperator(Type from, Type to) ...@@ -2489,7 +2555,7 @@ static MethodInfo GetOperator(Type from, Type to)
?? ResolveOperator(toMethods = to.GetMethods(BindingFlags.Static | BindingFlags.Public), from, to, "op_Implicit") ?? ResolveOperator(toMethods = to.GetMethods(BindingFlags.Static | BindingFlags.Public), from, to, "op_Implicit")
?? ResolveOperator(fromMethods, from, to, "op_Explicit") ?? ResolveOperator(fromMethods, from, to, "op_Explicit")
?? ResolveOperator(toMethods, from, to, "op_Explicit"); ?? ResolveOperator(toMethods, from, to, "op_Explicit");
} }
static MethodInfo ResolveOperator(MethodInfo[] methods, Type from, Type to, string name) static MethodInfo ResolveOperator(MethodInfo[] methods, Type from, Type to, string name)
{ {
...@@ -2730,7 +2796,7 @@ public IEnumerable<T> Read<T>(bool buffered = true) ...@@ -2730,7 +2796,7 @@ public IEnumerable<T> Read<T>(bool buffered = true)
/// <summary> /// <summary>
/// Read multiple objects from a single recordset on the grid /// Read multiple objects from a single recordset on the grid
/// </summary> /// </summary>
#if CSHARP30 #if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn, bool buffered) public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn, bool buffered)
#else #else
public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn = "id", bool buffered = true) public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn = "id", bool buffered = true)
...@@ -2752,7 +2818,7 @@ public IEnumerable<T> Read<T>(bool buffered = true) ...@@ -2752,7 +2818,7 @@ public IEnumerable<T> Read<T>(bool buffered = true)
/// <summary> /// <summary>
/// Read multiple objects from a single recordset on the grid /// Read multiple objects from a single recordset on the grid
/// </summary> /// </summary>
#if CSHARP30 #if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn, bool buffered) public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn, bool buffered)
#else #else
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn = "id", bool buffered = true) public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn = "id", bool buffered = true)
...@@ -2775,7 +2841,7 @@ public IEnumerable<T> Read<T>(bool buffered = true) ...@@ -2775,7 +2841,7 @@ public IEnumerable<T> Read<T>(bool buffered = true)
/// <summary> /// <summary>
/// Read multiple objects from a single record set on the grid /// Read multiple objects from a single record set on the grid
/// </summary> /// </summary>
#if CSHARP30 #if CSHARP30
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn, bool buffered) public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn, bool buffered)
#else #else
public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn = "id", bool buffered = true) public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn = "id", bool buffered = true)
...@@ -2896,7 +2962,10 @@ partial class ParamInfo ...@@ -2896,7 +2962,10 @@ partial class ParamInfo
/// <summary> /// <summary>
/// construct a dynamic parameter bag /// construct a dynamic parameter bag
/// </summary> /// </summary>
public DynamicParameters() { } public DynamicParameters()
{
RemoveUnused = true;
}
/// <summary> /// <summary>
/// construct a dynamic parameter bag /// construct a dynamic parameter bag
...@@ -2904,6 +2973,7 @@ partial class ParamInfo ...@@ -2904,6 +2973,7 @@ partial class ParamInfo
/// <param name="template">can be an anonymous type or a DynamicParameters bag</param> /// <param name="template">can be an anonymous type or a DynamicParameters bag</param>
public DynamicParameters(object template) public DynamicParameters(object template)
{ {
RemoveUnused = true;
AddDynamicParams(template); AddDynamicParams(template);
} }
...@@ -2914,7 +2984,7 @@ public DynamicParameters(object template) ...@@ -2914,7 +2984,7 @@ public DynamicParameters(object template)
/// <param name="param"></param> /// <param name="param"></param>
public void AddDynamicParams( public void AddDynamicParams(
#if CSHARP30 #if CSHARP30
object param object param
#else #else
dynamic param dynamic param
#endif #endif
...@@ -2976,7 +3046,7 @@ dynamic param ...@@ -2976,7 +3046,7 @@ dynamic param
/// <param name="size"></param> /// <param name="size"></param>
public void Add( public void Add(
#if CSHARP30 #if CSHARP30
string name, object value, DbType? dbType, ParameterDirection? direction, int? size string name, object value, DbType? dbType, ParameterDirection? direction, int? size
#else #else
string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null
#endif #endif
...@@ -3005,6 +3075,11 @@ void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Id ...@@ -3005,6 +3075,11 @@ void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Id
AddParameters(command, identity); AddParameters(command, identity);
} }
/// <summary>
/// If true, the command-text is inspected and only values that are clearly used are included on the connection
/// </summary>
public bool RemoveUnused { get; set; }
/// <summary> /// <summary>
/// Add all the parameters needed to the command just before it executes /// Add all the parameters needed to the command just before it executes
/// </summary> /// </summary>
...@@ -3023,7 +3098,7 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity) ...@@ -3023,7 +3098,7 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{ {
if (!paramReaderCache.TryGetValue(newIdent, out appender)) if (!paramReaderCache.TryGetValue(newIdent, out appender))
{ {
appender = SqlMapper.CreateParamInfoGenerator(newIdent, true); appender = SqlMapper.CreateParamInfoGenerator(newIdent, true, RemoveUnused);
paramReaderCache[newIdent] = appender; paramReaderCache[newIdent] = appender;
} }
} }
......
...@@ -78,7 +78,7 @@ internal class SomaConfig : Soma.Core.MsSqlConfig ...@@ -78,7 +78,7 @@ internal class SomaConfig : Soma.Core.MsSqlConfig
{ {
public override string ConnectionString public override string ConnectionString
{ {
get { return Program.connectionString; } get { return Program.ConnectionString; }
} }
public override void Log(Soma.Core.PreparedStatement preparedStatement) public override void Log(Soma.Core.PreparedStatement preparedStatement)
...@@ -134,17 +134,17 @@ public void Run(int iterations) ...@@ -134,17 +134,17 @@ public void Run(int iterations)
var mapperConnection3 = Program.GetOpenConnection(); var mapperConnection3 = Program.GetOpenConnection();
tests.Add(id => mapperConnection2.Get<Post>(id), "Dapper.Cotrib"); tests.Add(id => mapperConnection2.Get<Post>(id), "Dapper.Cotrib");
var massiveModel = new DynamicModel(Program.connectionString); var massiveModel = new DynamicModel(Program.ConnectionString);
var massiveConnection = Program.GetOpenConnection(); var massiveConnection = Program.GetOpenConnection();
tests.Add(id => massiveModel.Query("select * from Posts where Id = @0", massiveConnection, id).First(), "Dynamic Massive ORM Query"); tests.Add(id => massiveModel.Query("select * from Posts where Id = @0", massiveConnection, id).First(), "Dynamic Massive ORM Query");
// PetaPoco test with all default options // PetaPoco test with all default options
var petapoco = new PetaPoco.Database(Program.connectionString, "System.Data.SqlClient"); var petapoco = new PetaPoco.Database(Program.ConnectionString, "System.Data.SqlClient");
petapoco.OpenSharedConnection(); petapoco.OpenSharedConnection();
tests.Add(id => petapoco.Fetch<Post>("SELECT * from Posts where Id=@0", id), "PetaPoco (Normal)"); tests.Add(id => petapoco.Fetch<Post>("SELECT * from Posts where Id=@0", id), "PetaPoco (Normal)");
// PetaPoco with some "smart" functionality disabled // PetaPoco with some "smart" functionality disabled
var petapocoFast = new PetaPoco.Database(Program.connectionString, "System.Data.SqlClient"); var petapocoFast = new PetaPoco.Database(Program.ConnectionString, "System.Data.SqlClient");
petapocoFast.OpenSharedConnection(); petapocoFast.OpenSharedConnection();
petapocoFast.EnableAutoSelect = false; petapocoFast.EnableAutoSelect = false;
petapocoFast.EnableNamedParams = false; petapocoFast.EnableNamedParams = false;
...@@ -188,7 +188,7 @@ public void Run(int iterations) ...@@ -188,7 +188,7 @@ public void Run(int iterations)
tests.Add(id => db1.SetCommand("select * from Posts where Id = @id", db1.Parameter("id", id)).ExecuteList<Post>(), "BLToolkit"); tests.Add(id => db1.SetCommand("select * from Posts where Id = @id", db1.Parameter("id", id)).ExecuteList<Post>(), "BLToolkit");
// Simple.Data // Simple.Data
var sdb = Simple.Data.Database.OpenConnection(Program.connectionString); var sdb = Simple.Data.Database.OpenConnection(Program.ConnectionString);
tests.Add(id => sdb.Posts.FindById(id), "Simple.Data"); tests.Add(id => sdb.Posts.FindById(id), "Simple.Data");
// Soma // Soma
......
...@@ -28,11 +28,12 @@ class Post ...@@ -28,11 +28,12 @@ class Post
class Program class Program
{ {
public static readonly string connectionString = "Data Source=.;Initial Catalog=tempdb;Integrated Security=True"; public const string ConnectionString = "Data Source=.;Initial Catalog=tempdb;Integrated Security=True",
OleDbConnectionString = "Provider=SQLOLEDB;Data Source=.;Initial Catalog=tempdb;Integrated Security=SSPI";
public static SqlConnection GetOpenConnection() public static SqlConnection GetOpenConnection()
{ {
var connection = new SqlConnection(connectionString); var connection = new SqlConnection(ConnectionString);
connection.Open(); connection.Open();
return connection; return connection;
} }
......
...@@ -67,7 +67,7 @@ public PostWithConstructor(int id, int ownerid, string content) ...@@ -67,7 +67,7 @@ public PostWithConstructor(int id, int ownerid, string content)
} }
public void TestMultiMapWithConstructor() public void TestMultiMapWithConstructor()
{ {
var createSql = @" var createSql = @"
create table #Users (Id int, Name varchar(20)) create table #Users (Id int, Name varchar(20))
create table #Posts (Id int, OwnerId int, Content varchar(20)) create table #Posts (Id int, OwnerId int, Content varchar(20))
...@@ -79,20 +79,25 @@ public void TestMultiMapWithConstructor() ...@@ -79,20 +79,25 @@ public void TestMultiMapWithConstructor()
insert #Posts values(2, 99, 'Sams Post2') insert #Posts values(2, 99, 'Sams Post2')
insert #Posts values(3, null, 'no ones post')"; insert #Posts values(3, null, 'no ones post')";
connection.Execute(createSql); connection.Execute(createSql);
string sql = @"select * from #Posts p try
{
string sql = @"select * from #Posts p
left join #Users u on u.Id = p.OwnerId left join #Users u on u.Id = p.OwnerId
Order by p.Id"; Order by p.Id";
PostWithConstructor[] data = connection.Query<PostWithConstructor, UserWithConstructor, PostWithConstructor>(sql, (post, user) => { post.Owner = user; return post;}).ToArray(); PostWithConstructor[] data = connection.Query<PostWithConstructor, UserWithConstructor, PostWithConstructor>(sql, (post, user) => { post.Owner = user; return post; }).ToArray();
var p = data.First(); var p = data.First();
p.FullContent.IsEqualTo("Sams Post1");
p.Ident.IsEqualTo(1);
p.Owner.FullName.IsEqualTo("Sam");
p.Owner.Ident.IsEqualTo(99);
data[2].Owner.IsNull(); p.FullContent.IsEqualTo("Sams Post1");
p.Ident.IsEqualTo(1);
p.Owner.FullName.IsEqualTo("Sam");
p.Owner.Ident.IsEqualTo(99);
connection.Execute("drop table #Users drop table #Posts"); data[2].Owner.IsNull();
}
finally
{
connection.Execute("drop table #Users drop table #Posts");
}
} }
...@@ -159,7 +164,7 @@ public NoDefaultConstructor(int a1, int? b1, float f1, string s1, Guid G1) ...@@ -159,7 +164,7 @@ public NoDefaultConstructor(int a1, int? b1, float f1, string s1, Guid G1)
public void TestNoDefaultConstructor() public void TestNoDefaultConstructor()
{ {
var guid = Guid.NewGuid(); var guid = Guid.NewGuid();
NoDefaultConstructor nodef = connection.Query<NoDefaultConstructor>("select CAST(NULL AS integer) A1, CAST(NULL AS integer) b1, CAST(NULL AS real) f1, 'Dapper' s1, G1 = @id", new { Id = guid }).First(); NoDefaultConstructor nodef = connection.Query<NoDefaultConstructor>("select CAST(NULL AS integer) A1, CAST(NULL AS integer) b1, CAST(NULL AS real) f1, 'Dapper' s1, G1 = @id", new { id = guid }).First();
nodef.A.IsEqualTo(0); nodef.A.IsEqualTo(0);
nodef.B.IsEqualTo(null); nodef.B.IsEqualTo(null);
nodef.F.IsEqualTo(0); nodef.F.IsEqualTo(0);
...@@ -231,7 +236,7 @@ public void TestNoDefaultConstructorBinary() ...@@ -231,7 +236,7 @@ public void TestNoDefaultConstructorBinary()
} }
// http://stackoverflow.com/q/8593871 // http://stackoverflow.com/q/8593871
public void TestAbstractInheritance() public void TestAbstractInheritance()
{ {
var order = connection.Query<AbstractInheritance.ConcreteOrder>("select 1 Internal,2 Protected,3 [Public],4 Concrete").First(); var order = connection.Query<AbstractInheritance.ConcreteOrder>("select 1 Internal,2 Protected,3 [Public],4 Concrete").First();
...@@ -279,7 +284,7 @@ public enum TrapEnum : int ...@@ -279,7 +284,7 @@ public enum TrapEnum : int
#pragma warning restore 0649 #pragma warning restore 0649
public int Age { get; set; } public int Age { get; set; }
public TrapEnum Trap { get; set; } public TrapEnum Trap { get; set; }
} }
public void TestStructs() public void TestStructs()
...@@ -315,35 +320,46 @@ public void PassInEmptyIntArray() ...@@ -315,35 +320,46 @@ public void PassInEmptyIntArray()
public void TestSchemaChanged() public void TestSchemaChanged()
{ {
connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')"); connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')");
var d = connection.Query<Dog>("select * from #dog").Single(); try
d.Name.IsEqualTo("Alf"); {
d.Age.IsEqualTo(1); var d = connection.Query<Dog>("select * from #dog").Single();
connection.Execute("alter table #dog drop column Name"); d.Name.IsEqualTo("Alf");
d = connection.Query<Dog>("select * from #dog").Single(); d.Age.IsEqualTo(1);
d.Name.IsNull(); connection.Execute("alter table #dog drop column Name");
d.Age.IsEqualTo(1); d = connection.Query<Dog>("select * from #dog").Single();
connection.Execute("drop table #dog"); d.Name.IsNull();
d.Age.IsEqualTo(1);
}
finally
{
connection.Execute("drop table #dog");
}
} }
public void TestSchemaChangedMultiMap() public void TestSchemaChangedMultiMap()
{ {
connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')"); connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')");
var tuple = connection.Query<Dog, Dog, Tuple<Dog, Dog>>("select * from #dog d1 join #dog d2 on 1=1", (d1, d2) => Tuple.Create(d1, d2), splitOn: "Age").Single(); try
{
tuple.Item1.Name.IsEqualTo("Alf"); var tuple = connection.Query<Dog, Dog, Tuple<Dog, Dog>>("select * from #dog d1 join #dog d2 on 1=1", (d1, d2) => Tuple.Create(d1, d2), splitOn: "Age").Single();
tuple.Item1.Age.IsEqualTo(1);
tuple.Item2.Name.IsEqualTo("Alf");
tuple.Item2.Age.IsEqualTo(1);
connection.Execute("alter table #dog drop column Name"); tuple.Item1.Name.IsEqualTo("Alf");
tuple = connection.Query<Dog, Dog, Tuple<Dog, Dog>>("select * from #dog d1 join #dog d2 on 1=1", (d1, d2) => Tuple.Create(d1, d2), splitOn: "Age").Single(); tuple.Item1.Age.IsEqualTo(1);
tuple.Item2.Name.IsEqualTo("Alf");
tuple.Item2.Age.IsEqualTo(1);
tuple.Item1.Name.IsNull(); connection.Execute("alter table #dog drop column Name");
tuple.Item1.Age.IsEqualTo(1); tuple = connection.Query<Dog, Dog, Tuple<Dog, Dog>>("select * from #dog d1 join #dog d2 on 1=1", (d1, d2) => Tuple.Create(d1, d2), splitOn: "Age").Single();
tuple.Item2.Name.IsNull();
tuple.Item2.Age.IsEqualTo(1);
connection.Execute("drop table #dog"); tuple.Item1.Name.IsNull();
tuple.Item1.Age.IsEqualTo(1);
tuple.Item2.Name.IsNull();
tuple.Item2.Age.IsEqualTo(1);
}
finally
{
connection.Execute("drop table #dog");
}
} }
public void TestReadMultipleIntegersWithSplitOnAny() public void TestReadMultipleIntegersWithSplitOnAny()
...@@ -404,7 +420,7 @@ public void CheckComplexConcat() ...@@ -404,7 +420,7 @@ public void CheckComplexConcat()
string term = "F"; // the term the user searched for string term = "F"; // the term the user searched for
connection.Execute(@"create table #users16726709 (first_name varchar(200), last_name varchar(200)) connection.Execute(@"create table #users16726709 (first_name varchar(200), last_name varchar(200))
insert #users16726709 values ('Fred','Bloggs') insert #users16726709 values ('Tony','Farcus') insert #users16726709 values ('Albert','Tenof')"); insert #users16726709 values ('Fred','Bloggs') insert #users16726709 values ('Tony','Farcus') insert #users16726709 values ('Albert','TenoF')");
// Using Dapper // Using Dapper
connection.Query(end_wildcard, new { search_term = term }).Count().IsEqualTo(2); connection.Query(end_wildcard, new { search_term = term }).Count().IsEqualTo(2);
...@@ -462,7 +478,7 @@ public class Dog ...@@ -462,7 +478,7 @@ public class Dog
public void TestExtraFields() public void TestExtraFields()
{ {
var guid = Guid.NewGuid(); var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select '' as Extra, 1 as Age, 0.1 as Name1 , Id = @id", new { Id = guid }); var dog = connection.Query<Dog>("select '' as Extra, 1 as Age, 0.1 as Name1 , Id = @id", new { id = guid });
dog.Count() dog.Count()
.IsEqualTo(1); .IsEqualTo(1);
...@@ -474,6 +490,20 @@ public void TestExtraFields() ...@@ -474,6 +490,20 @@ public void TestExtraFields()
.IsEqualTo(guid); .IsEqualTo(guid);
} }
// see http://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?",
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
public void TestStrongType() public void TestStrongType()
{ {
...@@ -542,10 +572,17 @@ public void TestExecuteCommandWithHybridParameters() ...@@ -542,10 +572,17 @@ public void TestExecuteCommandWithHybridParameters()
public void TestExecuteMultipleCommand() public void TestExecuteMultipleCommand()
{ {
connection.Execute("create table #t(i int)"); connection.Execute("create table #t(i int)");
int tally = connection.Execute(@"insert #t (i) values(@a)", new[] { new { a = 1 }, new { a = 2 }, new { a = 3 }, new { a = 4 } }); try
int sum = connection.Query<int>("select sum(i) from #t drop table #t").First(); {
tally.IsEqualTo(4); int tally = connection.Execute(@"insert #t (i) values(@a)", new[] { new { a = 1 }, new { a = 2 }, new { a = 3 }, new { a = 4 } });
sum.IsEqualTo(10); int sum = connection.Query<int>("select sum(i) from #t").First();
tally.IsEqualTo(4);
sum.IsEqualTo(10);
}
finally
{
connection.Execute("drop table #t");
}
} }
class Student class Student
...@@ -557,14 +594,21 @@ class Student ...@@ -557,14 +594,21 @@ class Student
public void TestExecuteMultipleCommandStrongType() public void TestExecuteMultipleCommandStrongType()
{ {
connection.Execute("create table #t(Name nvarchar(max), Age int)"); connection.Execute("create table #t(Name nvarchar(max), Age int)");
int tally = connection.Execute(@"insert #t (Name,Age) values(@Name, @Age)", new List<Student> try
{
int tally = connection.Execute(@"insert #t (Name,Age) values(@Name, @Age)", new List<Student>
{ {
new Student{Age = 1, Name = "sam"}, new Student{Age = 1, Name = "sam"},
new Student{Age = 2, Name = "bob"} new Student{Age = 2, Name = "bob"}
}); });
int sum = connection.Query<int>("select sum(Age) from #t drop table #t").First(); int sum = connection.Query<int>("select sum(Age) from #t").First();
tally.IsEqualTo(2); tally.IsEqualTo(2);
sum.IsEqualTo(3); sum.IsEqualTo(3);
}
finally
{
connection.Execute("drop table #t");
}
} }
public void TestExecuteMultipleCommandObjectArray() public void TestExecuteMultipleCommandObjectArray()
...@@ -591,7 +635,7 @@ class TestObj ...@@ -591,7 +635,7 @@ class TestObj
public int _priv; public int _priv;
private int Priv { set { _priv = value; } } private int Priv { set { _priv = value; } }
private int PrivGet { get { return _priv;} } private int PrivGet { get { return _priv; } }
} }
public void TestSetInternal() public void TestSetInternal()
...@@ -608,7 +652,7 @@ public void TestSetPrivate() ...@@ -608,7 +652,7 @@ public void TestSetPrivate()
public void TestExpandWithNullableFields() public void TestExpandWithNullableFields()
{ {
var row = connection.Query("select null A, 2 B").Single(); var row = connection.Query("select null A, 2 B").Single();
((int?)row.A) ((int?)row.A)
.IsNull(); .IsNull();
...@@ -712,23 +756,27 @@ public void TestMultiMap() ...@@ -712,23 +756,27 @@ public void TestMultiMap()
insert #Posts values(3, null, 'no ones post') insert #Posts values(3, null, 'no ones post')
"; ";
connection.Execute(createSql); connection.Execute(createSql);
try
var sql = {
@"select * from #Posts p var sql =
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId left join #Users u on u.Id = p.OwnerId
Order by p.Id"; Order by p.Id";
var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }).ToList(); var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }).ToList();
var p = data.First(); var p = data.First();
p.Content.IsEqualTo("Sams Post1");
p.Id.IsEqualTo(1);
p.Owner.Name.IsEqualTo("Sam");
p.Owner.Id.IsEqualTo(99);
data[2].Owner.IsNull(); p.Content.IsEqualTo("Sams Post1");
p.Id.IsEqualTo(1);
p.Owner.Name.IsEqualTo("Sam");
p.Owner.Id.IsEqualTo(99);
connection.Execute("drop table #Users drop table #Posts"); data[2].Owner.IsNull();
}
finally
{
connection.Execute("drop table #Users drop table #Posts");
}
} }
...@@ -807,7 +855,7 @@ public void TestQueryMultipleNonBufferedIncorrectOrder() ...@@ -807,7 +855,7 @@ public void TestQueryMultipleNonBufferedIncorrectOrder()
{ {
// that's expected // that's expected
} }
} }
} }
public void TestQueryMultipleNonBufferedCcorrectOrder() public void TestQueryMultipleNonBufferedCcorrectOrder()
...@@ -1592,26 +1640,30 @@ public void TestMultiMapThreeTypesWithGridReader() ...@@ -1592,26 +1640,30 @@ public void TestMultiMapThreeTypesWithGridReader()
insert #Comments values(1, 1, 'Comment 1')"; insert #Comments values(1, 1, 'Comment 1')";
connection.Execute(createSql); connection.Execute(createSql);
try
var sql = @"SELECT p.* FROM #Posts p {
var sql = @"SELECT p.* FROM #Posts p
select p.*, u.Id, u.Name + '0' Name, c.Id, c.CommentData from #Posts p select p.*, u.Id, u.Name + '0' Name, c.Id, c.CommentData from #Posts p
left join #Users u on u.Id = p.OwnerId left join #Users u on u.Id = p.OwnerId
left join #Comments c on c.postId = p.Id left join #Comments c on c.PostId = p.Id
where p.Id = 1 where p.Id = 1
Order by p.Id"; Order by p.Id";
var grid = connection.QueryMultiple(sql); var grid = connection.QueryMultiple(sql);
var post1 = grid.Read<Post>().ToList();
var post2 = grid.Read<Post, User, Comment, Post>((post, user, comment) => { post.Owner = user; post.Comment = comment; return post; }).SingleOrDefault(); var post1 = grid.Read<Post>().ToList();
post2.Comment.Id.IsEqualTo(1); var post2 = grid.Read<Post, User, Comment, Post>((post, user, comment) => { post.Owner = user; post.Comment = comment; return post; }).SingleOrDefault();
post2.Owner.Id.IsEqualTo(99);
post2.Comment.Id.IsEqualTo(1);
post2.Owner.Id.IsEqualTo(99);
connection.Execute("drop table #Users drop table #Posts drop table #Comments"); }
finally
{
connection.Execute("drop table #Users drop table #Posts drop table #Comments");
}
} }
public class DbParams : Dapper.SqlMapper.IDynamicParameters, IEnumerable<IDbDataParameter> public class DbParams : Dapper.SqlMapper.IDynamicParameters, IEnumerable<IDbDataParameter>
...@@ -1656,24 +1708,28 @@ public void TestReadDynamicWithGridReader() ...@@ -1656,24 +1708,28 @@ public void TestReadDynamicWithGridReader()
insert #Posts values(1, 99, 'Sams Post1') insert #Posts values(1, 99, 'Sams Post1')
insert #Posts values(2, 99, 'Sams Post2') insert #Posts values(2, 99, 'Sams Post2')
insert #Posts values(3, null, 'no ones post')"; insert #Posts values(3, null, 'no ones post')";
try
{
connection.Execute(createSql);
connection.Execute(createSql); var sql = @"SELECT * FROM #Users ORDER BY Id
var sql = @"SELECT * FROM #Users ORDER BY Id
SELECT * FROM #Posts ORDER BY Id DESC"; SELECT * FROM #Posts ORDER BY Id DESC";
var grid = connection.QueryMultiple(sql); var grid = connection.QueryMultiple(sql);
var users = grid.Read().ToList();
var posts = grid.Read().ToList();
users.Count.IsEqualTo(2); var users = grid.Read().ToList();
posts.Count.IsEqualTo(3); var posts = grid.Read().ToList();
((int)users.First().Id).IsEqualTo(2); users.Count.IsEqualTo(2);
((int)posts.First().Id).IsEqualTo(3); posts.Count.IsEqualTo(3);
connection.Execute("drop table #Users drop table #Posts"); ((int)users.First().Id).IsEqualTo(2);
((int)posts.First().Id).IsEqualTo(3);
}
finally
{
connection.Execute("drop table #Users drop table #Posts");
}
} }
public void TestDynamicParamNullSupport() public void TestDynamicParamNullSupport()
...@@ -2056,7 +2112,7 @@ public void TestReaderWhenResultsChange() ...@@ -2056,7 +2112,7 @@ public void TestReaderWhenResultsChange()
{ {
try try
{ {
connection.Execute("create table #ResultsChange (X int);create table #ResultsChange2 (Y int);insert #ResultsChange (X) values(1);insert #ResultsChange2 (Y) values(1);"); connection.Execute("create table #ResultsChange (X int);create table #ResultsChange2 (Y int);insert #ResultsChange (X) values(1);insert #ResultsChange2 (Y) values(1);");
var obj1 = connection.Query<ResultsChangeType>("select * from #ResultsChange").Single(); var obj1 = connection.Query<ResultsChangeType>("select * from #ResultsChange").Single();
...@@ -2081,7 +2137,8 @@ public void TestReaderWhenResultsChange() ...@@ -2081,7 +2137,8 @@ public void TestReaderWhenResultsChange()
obj4.X.IsEqualTo(1); obj4.X.IsEqualTo(1);
obj4.Y.IsEqualTo(1); obj4.Y.IsEqualTo(1);
obj4.Z.IsEqualTo(2); obj4.Z.IsEqualTo(2);
} finally }
finally
{ {
connection.Execute("drop table #ResultsChange;drop table #ResultsChange2;"); connection.Execute("drop table #ResultsChange;drop table #ResultsChange2;");
} }
...@@ -2101,7 +2158,7 @@ public void TestCustomTypeMap() ...@@ -2101,7 +2158,7 @@ public void TestCustomTypeMap()
item.B.IsEqualTo("BVal"); item.B.IsEqualTo("BVal");
// custom mapping // custom mapping
var map = new CustomPropertyTypeMap(typeof(TypeWithMapping), var map = new CustomPropertyTypeMap(typeof(TypeWithMapping),
(type, columnName) => type.GetProperties().Where(prop => prop.GetCustomAttributes(false).OfType<DescriptionAttribute>().Any(attr => attr.Description == columnName)).FirstOrDefault()); (type, columnName) => type.GetProperties().Where(prop => prop.GetCustomAttributes(false).OfType<DescriptionAttribute>().Any(attr => attr.Description == columnName)).FirstOrDefault());
Dapper.SqlMapper.SetTypeMap(typeof(TypeWithMapping), map); Dapper.SqlMapper.SetTypeMap(typeof(TypeWithMapping), map);
...@@ -2132,7 +2189,7 @@ public class WrongTypes ...@@ -2132,7 +2189,7 @@ public class WrongTypes
public long C { get; set; } public long C { get; set; }
public bool D { get; set; } public bool D { get; set; }
} }
public void TestWrongTypes_WithRightTypes() public void TestWrongTypes_WithRightTypes()
{ {
var item = connection.Query<WrongTypes>("select 1 as A, cast(2.0 as float) as B, cast(3 as bigint) as C, cast(1 as bit) as D").Single(); var item = connection.Query<WrongTypes>("select 1 as A, cast(2.0 as float) as B, cast(3 as bigint) as C, cast(1 as bit) as D").Single();
...@@ -2141,7 +2198,7 @@ public void TestWrongTypes_WithRightTypes() ...@@ -2141,7 +2198,7 @@ public void TestWrongTypes_WithRightTypes()
item.C.Equals(3L); item.C.Equals(3L);
item.D.Equals(true); item.D.Equals(true);
} }
public void TestWrongTypes_WithWrongTypes() public void TestWrongTypes_WithWrongTypes()
{ {
var item = connection.Query<WrongTypes>("select cast(1.0 as float) as A, 2 as B, 3 as C, cast(1 as bigint) as D").Single(); var item = connection.Query<WrongTypes>("select cast(1.0 as float) as A, 2 as B, 3 as C, cast(1 as bigint) as D").Single();
...@@ -2193,14 +2250,14 @@ public void Issue_40_AutomaticBoolConversion() ...@@ -2193,14 +2250,14 @@ public void Issue_40_AutomaticBoolConversion()
public class Issue40_User public class Issue40_User
{ {
public Issue40_User() public Issue40_User()
{ {
Email = Password = String.Empty; Email = Password = String.Empty;
} }
public int UserID { get; set; } public int UserID { get; set; }
public string Email { get; set; } public string Email { get; set; }
public string Password { get; set; } public string Password { get; set; }
public bool Active { get; set; } public bool Active { get; set; }
} }
SqlConnection GetClosedConnection() SqlConnection GetClosedConnection()
...@@ -2324,11 +2381,13 @@ public void TestMultiSelectWithSomeEmptyGrids() ...@@ -2324,11 +2381,13 @@ public void TestMultiSelectWithSomeEmptyGrids()
var two = reader.Read<int>().ToArray(); var two = reader.Read<int>().ToArray();
var three = reader.Read<int>().ToArray(); var three = reader.Read<int>().ToArray();
var four = reader.Read<int>().ToArray(); var four = reader.Read<int>().ToArray();
try { // only returned four grids; expect a fifth read to fail try
{ // only returned four grids; expect a fifth read to fail
reader.Read<int>(); reader.Read<int>();
throw new InvalidOperationException("this should not have worked!"); throw new InvalidOperationException("this should not have worked!");
} }
catch (ObjectDisposedException ex) { // expected; success catch (ObjectDisposedException ex)
{ // expected; success
ex.Message.IsEqualTo("The reader has been disposed; this can happen after all data has been consumed\r\nObject name: 'Dapper.SqlMapper+GridReader'."); ex.Message.IsEqualTo("The reader has been disposed; this can happen after all data has been consumed\r\nObject name: 'Dapper.SqlMapper+GridReader'.");
} }
...@@ -2345,7 +2404,7 @@ public void TestDynamicMutation() ...@@ -2345,7 +2404,7 @@ public void TestDynamicMutation()
{ {
var obj = connection.Query("select 1 as [a], 2 as [b], 3 as [c]").Single(); var obj = connection.Query("select 1 as [a], 2 as [b], 3 as [c]").Single();
((int)obj.a).IsEqualTo(1); ((int)obj.a).IsEqualTo(1);
IDictionary<string,object> dict = obj; IDictionary<string, object> dict = obj;
Assert.Equals(3, dict.Count); Assert.Equals(3, dict.Count);
Assert.IsTrue(dict.Remove("a")); Assert.IsTrue(dict.Remove("a"));
Assert.IsFalse(dict.Remove("d")); Assert.IsFalse(dict.Remove("d"));
...@@ -2501,30 +2560,30 @@ public void Open() ...@@ -2501,30 +2560,30 @@ public void Open()
} }
} }
public void TestDapperTableMetadataRetrieval() public void TestDapperTableMetadataRetrieval()
{ {
// Test for a bug found in CS 51509960 where the following sequence would result in an InvalidOperationException being // Test for a bug found in CS 51509960 where the following sequence would result in an InvalidOperationException being
// thrown due to an attempt to access a disposed of DataReader: // thrown due to an attempt to access a disposed of DataReader:
// //
// - Perform a dynamic query that yields no results // - Perform a dynamic query that yields no results
// - Add data to the source of that query // - Add data to the source of that query
// - Perform a the same query again // - Perform a the same query again
connection.Execute("CREATE TABLE #sut (value varchar(10) NOT NULL PRIMARY KEY)"); connection.Execute("CREATE TABLE #sut (value varchar(10) NOT NULL PRIMARY KEY)");
connection.Query("SELECT value FROM #sut").IsSequenceEqualTo(Enumerable.Empty<dynamic>()); connection.Query("SELECT value FROM #sut").IsSequenceEqualTo(Enumerable.Empty<dynamic>());
connection.Execute("INSERT INTO #sut (value) VALUES ('test')").IsEqualTo(1); connection.Execute("INSERT INTO #sut (value) VALUES ('test')").IsEqualTo(1);
var result = connection.Query("SELECT value FROM #sut"); var result = connection.Query("SELECT value FROM #sut");
var first = result.First(); var first = result.First();
((string)first.value).IsEqualTo("test"); ((string)first.value).IsEqualTo("test");
} }
public void TestIssue17648290() public void TestIssue17648290()
{ {
var p = new DynamicParameters(); var p = new DynamicParameters();
int code = 1, getMessageControlId = 2; int code = 1, getMessageControlId = 2;
p.Add("@Code", code); p.Add("@Code", code);
p.Add("@MessageControlId", getMessageControlId); p.Add("@MessageControlID", getMessageControlId);
p.Add("@SuccessCode", dbType: DbType.Int32, direction: ParameterDirection.Output); p.Add("@SuccessCode", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@ErrorDescription", dbType: DbType.String, direction: ParameterDirection.Output, size: 255); p.Add("@ErrorDescription", dbType: DbType.String, direction: ParameterDirection.Output, size: 255);
connection.Execute(@"CREATE PROCEDURE #up_MessageProcessed_get connection.Execute(@"CREATE PROCEDURE #up_MessageProcessed_get
......
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Npgsql</id>
<version>2.0.11</version>
<title>Npgsql</title>
<authors>Jon Asher, Brar Piening, Chris Morgan, Dave Page, Federico Di Gregorio, Francisco Figueiredo jr., Hiroshi Saito, Josh Cooley, Jon Hanna</authors>
<owners>Jon Asher, Brar Piening, Chris Morgan, Dave Page, Federico Di Gregorio, Francisco Figueiredo jr., Hiroshi Saito, Josh Cooley, Jon Hanna</owners>
<licenseUrl>http://www.opensource.org/licenses/bsd-license.php</licenseUrl>
<projectUrl>http://pgfoundry.org/projects/npgsql/</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Npgsql is a .Net data provider for Postgresql. It allows any program developed for .Net framework to access database server. It is implemented in 100% C# code. Works with Postgresql 7.x and 8.x.</description>
<summary>Npgsql is a .Net data provider for Postgresql.</summary>
<tags>Npgsql postgres data database</tags>
</metadata>
</package>
\ No newline at end of file
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>NuGet.CommandLine</id>
<version>2.0.40001</version>
<authors>Outercurve Foundation</authors>
<owners>Outercurve Foundation</owners>
<licenseUrl>http://nuget.codeplex.com/license</licenseUrl>
<projectUrl>http://nuget.codeplex.com/</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>NuGet Command Line Tool</description>
</metadata>
</package>
\ No newline at end of file
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