Commit 047eef9f authored by Sam Saffron's avatar Sam Saffron

added execute command

parent 53e7f518
...@@ -109,33 +109,28 @@ public bool Equals(Identity other) ...@@ -109,33 +109,28 @@ public bool Equals(Identity other)
static Dictionary<Type, SqlDbType> typeMap; static Dictionary<Type, SqlDbType> typeMap;
/// <summary>
/// Execute parameterized SQL
/// </summary>
/// <returns>Number of rows affected</returns>
public static int ExecuteMapperCommand(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)
{
return ExecuteCommand(cnn, transaction, sql, GetParamInfo(param));
}
public static List<dynamic> ExecuteMapperQuery (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null) public static List<dynamic> ExecuteMapperQuery (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)
{ {
// TODO: get rid of casting hackery // TODO: get rid of casting hackery
return ExecuteMapperQuery<ExpandoObject>(cnn, sql, param, transaction).Select(s => s as dynamic).ToList(); return ExecuteMapperQuery<ExpandoObject>(cnn, sql, param, transaction).Select(s => s as dynamic).ToList();
} }
public static List<T> ExecuteMapperQuery<T>(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null) public static List<T> ExecuteMapperQuery<T>(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)
{ {
var identity = new Identity(sql, typeof(T)); var identity = new Identity(sql, typeof(T));
var rval = new List<T>(); var rval = new List<T>();
using (var reader = GetReader(cnn, transaction, sql, GetParamInfo(param)))
Func<object, List<ParamInfo>> paramInfoGenerator;
List<ParamInfo> paramInfo = null;
if (param != null)
{
if (!cachedParamReaders.TryGetValue(param.GetType(), out paramInfoGenerator))
{
paramInfoGenerator = CreateParamInfoGenerator(param.GetType());
cachedParamReaders[param.GetType()] = paramInfoGenerator;
}
paramInfo = paramInfoGenerator(param);
}
using (var reader = GetReader<T>(cnn, transaction, sql, paramInfo))
{ {
object oDeserializer; object oDeserializer;
if (!cachedSerializers.TryGetValue(identity, out oDeserializer)) if (!cachedSerializers.TryGetValue(identity, out oDeserializer))
...@@ -167,6 +162,24 @@ public static List<T> ExecuteMapperQuery<T>(this IDbConnection cnn, string sql, ...@@ -167,6 +162,24 @@ public static List<T> ExecuteMapperQuery<T>(this IDbConnection cnn, string sql,
return rval; return rval;
} }
private static List<ParamInfo> GetParamInfo(object param)
{
Func<object, List<ParamInfo>> paramInfoGenerator;
List<ParamInfo> paramInfo = null;
if (param != null)
{
if (!cachedParamReaders.TryGetValue(param.GetType(), out paramInfoGenerator))
{
paramInfoGenerator = CreateParamInfoGenerator(param.GetType());
cachedParamReaders[param.GetType()] = paramInfoGenerator;
}
paramInfo = paramInfoGenerator(param);
}
return paramInfo;
}
private static object GetDynamicDeserializer(IDataReader reader) private static object GetDynamicDeserializer(IDataReader reader)
{ {
List<string> colNames = new List<string>(); List<string> colNames = new List<string>();
...@@ -228,60 +241,75 @@ private static object GetDynamicDeserializer(IDataReader reader) ...@@ -228,60 +241,75 @@ private static object GetDynamicDeserializer(IDataReader reader)
return (Func<object, List<ParamInfo>>)dm.CreateDelegate(typeof(Func<object, List<ParamInfo>>)); return (Func<object, List<ParamInfo>>)dm.CreateDelegate(typeof(Func<object, List<ParamInfo>>));
} }
private static IDbCommand SetupCommand(IDbConnection cnn, SqlTransaction tranaction, string sql, List<ParamInfo> paramInfo)
private static IDataReader GetReader<T>(IDbConnection cnn, SqlTransaction tranaction, string sql, List<ParamInfo> paramInfo)
{ {
using (var cmd = cnn.CreateCommand()) var cmd = cnn.CreateCommand();
cmd.Transaction = tranaction;
cmd.CommandText = sql;
if (paramInfo != null)
{ {
cmd.Transaction = tranaction; foreach (var info in paramInfo)
cmd.CommandText = sql;
if (paramInfo != null)
{ {
foreach (var info in paramInfo) var param = new SqlParameter("@" + info.Name, info.Type);
param.Value = info.Val ?? DBNull.Value;
param.Direction = ParameterDirection.Input;
if (info.Type == SqlDbType.NVarChar)
{ {
var param = new SqlParameter("@" + info.Name, info.Type); param.Size = 4000;
}
param.Value = info.Val ?? DBNull.Value; if (info.Type == SqlDbType.Structured)
param.Direction = ParameterDirection.Input; {
if (info.Type == SqlDbType.NVarChar)
{
param.Size = 4000;
}
if (info.Type == SqlDbType.Structured) // initially we tried TVP, however it performs quite poorly.
{ // keep in mind SQL support up to 2000 params easily in sp_executesql, needing more is rare
// initially we tried TVP, however it performs quite poorly. var list = info.Val as IEnumerable;
// keep in mind SQL support up to 2000 params easily in sp_executesql, needing more is rare var count = 0;
var list = info.Val as IEnumerable; if (list != null)
var count = 0; {
foreach (var item in list)
if (list != null)
{
foreach (var item in list)
{
count++;
cmd.Parameters.Add(new SqlParameter("@" + info.Name + count, item));
}
cmd.CommandText = cmd.CommandText.Replace("@" + info.Name,
"(" + string.Join(
",", Enumerable.Range(1, count).Select(i => "@" + info.Name + i)
) + ")");
}
else
{ {
throw new NotImplementedException(); count++;
cmd.Parameters.Add(new SqlParameter("@" + info.Name + count, item));
} }
cmd.CommandText = cmd.CommandText.Replace("@" + info.Name,
"(" + string.Join(
",", Enumerable.Range(1, count).Select(i => "@" + info.Name + i)
) + ")");
} }
else else
{ {
cmd.Parameters.Add(param); throw new NotImplementedException();
} }
} }
else
{
cmd.Parameters.Add(param);
}
} }
}
return cmd;
}
private static int ExecuteCommand(IDbConnection cnn, SqlTransaction tranaction, string sql, List<ParamInfo> paramInfo)
{
using (var cmd = SetupCommand(cnn, tranaction, sql, paramInfo))
{
return cmd.ExecuteNonQuery();
}
}
private static IDataReader GetReader(IDbConnection cnn, SqlTransaction tranaction, string sql, List<ParamInfo> paramInfo)
{
using (var cmd = SetupCommand(cnn, tranaction, sql, paramInfo))
{
return cmd.ExecuteReader(); return cmd.ExecuteReader();
} }
} }
......
...@@ -118,10 +118,22 @@ public void TestExpando() ...@@ -118,10 +118,22 @@ public void TestExpando()
} }
public void TestStringList() public void TestStringList()
{ {
connection.ExecuteMapperQuery<string>("select * from (select 'a' as x union all select 'b' union all select 'c') as T where x in @strings", new {strings = new[] {"a","b","c"}}) connection.ExecuteMapperQuery<string>("select * from (select 'a' as x union all select 'b' union all select 'c') as T where x in @strings", new {strings = new[] {"a","b","c"}})
.IsSequenceEqual(new[] {"a","b","c"}); .IsSequenceEqual(new[] {"a","b","c"});
} }
public void TestExecuteCommand()
{
connection.ExecuteMapperCommand(@"
set nocount on
create table #t(i int)
set nocount off
insert #t
select @a a union all select @b
set nocount on
drop table #t", new {a=1, b=2 }).IsEquals(2);
}
} }
} }
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