Commit d7443490 authored by Sam's avatar Sam

Merge pull request #32 from brannon/master

Add support for dictionaries/expandos to DynamicParameters + Refactoring
parents d0b9bf9c 081799e6
...@@ -1372,6 +1372,7 @@ private static IDbCommand SetupCommand(IDbConnection cnn, IDbTransaction transac ...@@ -1372,6 +1372,7 @@ private static IDbCommand SetupCommand(IDbConnection cnn, IDbTransaction transac
var cmd = cnn.CreateCommand(); var cmd = cnn.CreateCommand();
var bindByName = GetBindByName(cmd.GetType()); var bindByName = GetBindByName(cmd.GetType());
if (bindByName != null) bindByName(cmd, true); if (bindByName != null) bindByName(cmd, true);
if (transaction != null)
cmd.Transaction = transaction; cmd.Transaction = transaction;
cmd.CommandText = sql; cmd.CommandText = sql;
if (commandTimeout.HasValue) if (commandTimeout.HasValue)
...@@ -1584,33 +1585,22 @@ static List<FieldInfo> GetSettableFields(Type t) ...@@ -1584,33 +1585,22 @@ static List<FieldInfo> GetSettableFields(Type t)
il.Emit(OpCodes.Pop); // stack is now [target][target] il.Emit(OpCodes.Pop); // stack is now [target][target]
il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [target][target][enum-type-token] il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [target][target][enum-type-token]
il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null);// stack is now [target][target][enum-type] il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null);// stack is now [target][target][enum-type]
il.Emit(OpCodes.Ldloc_2); // stack is now [target][target][enum-type][string] il.Emit(OpCodes.Ldloc_2); // stack is now [target][target][enum-type][string]
il.Emit(OpCodes.Ldc_I4_1); // stack is now [target][target][enum-type][string][true] il.Emit(OpCodes.Ldc_I4_1); // stack is now [target][target][enum-type][string][true]
il.EmitCall(OpCodes.Call, enumParse, null); // stack is now [target][target][enum-as-object] il.EmitCall(OpCodes.Call, enumParse, null); // stack is now [target][target][enum-as-object]
il.MarkLabel(isNotString);
il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value] il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value]
if (nullUnderlyingType != null) if (nullUnderlyingType != null)
{ {
il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType })); il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType })); // stack is now [target][target][enum-value]
}
if (item.Property != null)
{
il.Emit(OpCodes.Callvirt, item.Property.Setter); // stack is now [target]
}
else
{
il.Emit(OpCodes.Stfld, item.Field); // stack is now [target]
} }
il.Emit(OpCodes.Br_S, finishLabel);
il.MarkLabel(isNotString);
} }
if (memberType.FullName == LinqBinary) else if (memberType.FullName == LinqBinary)
{ {
il.Emit(OpCodes.Unbox_Any, typeof(byte[])); // stack is now [target][target][byte-array] il.Emit(OpCodes.Unbox_Any, typeof(byte[])); // stack is now [target][target][byte-array]
il.Emit(OpCodes.Newobj, memberType.GetConstructor(new Type[] { typeof(byte[]) }));// stack is now [target][target][binary] il.Emit(OpCodes.Newobj, memberType.GetConstructor(new Type[] { typeof(byte[]) }));// stack is now [target][target][binary]
...@@ -1619,11 +1609,9 @@ static List<FieldInfo> GetSettableFields(Type t) ...@@ -1619,11 +1609,9 @@ static List<FieldInfo> GetSettableFields(Type t)
{ {
il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value] il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value]
} }
if (nullUnderlyingType != null && nullUnderlyingType.IsEnum)
{
il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType }));
}
} }
// Store the value in the property/field
if (item.Property != null) if (item.Property != null)
{ {
if (type.IsValueType) if (type.IsValueType)
...@@ -1975,17 +1963,15 @@ class ParamInfo ...@@ -1975,17 +1963,15 @@ class ParamInfo
/// construct a dynamic parameter bag /// construct a dynamic parameter bag
/// </summary> /// </summary>
public DynamicParameters() { } public DynamicParameters() { }
/// <summary> /// <summary>
/// construct a dynamic parameter bag /// construct a dynamic parameter bag
/// </summary> /// </summary>
/// <param name="template">can be an anonymous type of a DynamicParameters bag</param> /// <param name="template">can be an anonymous type of a DynamicParameters bag</param>
public DynamicParameters(object template) public DynamicParameters(object template)
{
if (template != null)
{ {
AddDynamicParams(template); AddDynamicParams(template);
} }
}
/// <summary> /// <summary>
/// Append a whole object full of params to the dynamic /// Append a whole object full of params to the dynamic
...@@ -2000,18 +1986,31 @@ dynamic param ...@@ -2000,18 +1986,31 @@ dynamic param
#endif #endif
) )
{ {
object obj = param as object; var obj = param as object;
if (obj != null) if (obj != null)
{ {
var subDynamic = obj as DynamicParameters; var subDynamic = obj as DynamicParameters;
if (subDynamic == null) if (subDynamic == null)
{
var dictionary = obj as IEnumerable<KeyValuePair<string, object>>;
if (dictionary == null)
{ {
templates = templates ?? new List<object>(); templates = templates ?? new List<object>();
templates.Add(obj); templates.Add(obj);
} }
else else
{
foreach (var kvp in dictionary)
{
#if CSHARP30
Add(kvp.Key, kvp.Value, null, null, null);
#else
Add(kvp.Key, kvp.Value);
#endif
}
}
}
else
{ {
if (subDynamic.parameters != null) if (subDynamic.parameters != null)
{ {
......
...@@ -769,12 +769,6 @@ public void TestEnumWeirdness() ...@@ -769,12 +769,6 @@ public void TestEnumWeirdness()
connection.Query<TestEnumClass>("select null as [EnumEnum]").First().EnumEnum.IsEqualTo(null); connection.Query<TestEnumClass>("select null as [EnumEnum]").First().EnumEnum.IsEqualTo(null);
connection.Query<TestEnumClass>("select cast(1 as tinyint) as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); connection.Query<TestEnumClass>("select cast(1 as tinyint) as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
} }
void Foo()
{
string s = "Bla";
var obj = new TestEnumClassNoNull();
obj.EnumEnum = (TestEnum)Enum.Parse(typeof(TestEnum), s, true);
}
public void TestEnumStrings() public void TestEnumStrings()
{ {
connection.Query<TestEnumClassNoNull>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); connection.Query<TestEnumClassNoNull>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
...@@ -784,7 +778,7 @@ public void TestEnumStrings() ...@@ -784,7 +778,7 @@ public void TestEnumStrings()
connection.Query<TestEnumClass>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla); connection.Query<TestEnumClass>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
} }
public void TestSupportForParamDictionary() public void TestSupportForDynamicParameters()
{ {
var p = new DynamicParameters(); var p = new DynamicParameters();
p.Add("name", "bob"); p.Add("name", "bob");
...@@ -795,7 +789,6 @@ public void TestSupportForParamDictionary() ...@@ -795,7 +789,6 @@ public void TestSupportForParamDictionary()
p.Get<int>("age").IsEqualTo(11); p.Get<int>("age").IsEqualTo(11);
} }
public void TestProcSupport() public void TestProcSupport()
{ {
var p = new DynamicParameters(); var p = new DynamicParameters();
...@@ -1256,6 +1249,36 @@ public void TestAppendingAnonClasses() ...@@ -1256,6 +1249,36 @@ public void TestAppendingAnonClasses()
((int)result.d).IsEqualTo(4); ((int)result.d).IsEqualTo(4);
} }
public void TestAppendingADictionary()
{
var dictionary = new Dictionary<string, object>();
dictionary.Add("A", 1);
dictionary.Add("B", "two");
DynamicParameters p = new DynamicParameters();
p.AddDynamicParams(dictionary);
var result = connection.Query("select @A a, @B b", p).Single();
((int)result.a).IsEqualTo(1);
((string)result.b).IsEqualTo("two");
}
public void TestAppendingAnExpandoObject()
{
dynamic expando = new System.Dynamic.ExpandoObject();
expando.A = 1;
expando.B = "two";
DynamicParameters p = new DynamicParameters();
p.AddDynamicParams(expando);
var result = connection.Query("select @A a, @B b", p).Single();
((int)result.a).IsEqualTo(1);
((string)result.b).IsEqualTo("two");
}
public void TestAppendingAList() public void TestAppendingAList()
{ {
DynamicParameters p = new DynamicParameters(); DynamicParameters p = new DynamicParameters();
...@@ -1393,6 +1416,126 @@ public enum ShortEnum : short ...@@ -1393,6 +1416,126 @@ public enum ShortEnum : short
Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6 Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6
} }
public void TestTransactionCommit()
{
try
{
connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
using (var transaction = connection.BeginTransaction())
{
connection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');", transaction: transaction);
transaction.Commit();
}
connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(1);
}
finally
{
connection.Execute("drop table #TransactionTest;");
}
}
public void TestTransactionRollback()
{
connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
try
{
using (var transaction = connection.BeginTransaction())
{
connection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');", transaction: transaction);
transaction.Rollback();
}
connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(0);
}
finally
{
connection.Execute("drop table #TransactionTest;");
}
}
public void TestCommandWithInheritedTransaction()
{
connection.Execute("create table #TransactionTest ([ID] int, [Value] varchar(32));");
try
{
using (var transaction = connection.BeginTransaction())
{
var transactedConnection = new TransactedConnection(connection, transaction);
transactedConnection.Execute("insert into #TransactionTest ([ID], [Value]) values (1, 'ABC');");
transaction.Rollback();
}
connection.Query<int>("select count(*) from #TransactionTest;").Single().IsEqualTo(0);
}
finally
{
connection.Execute("drop table #TransactionTest;");
}
}
class TransactedConnection : IDbConnection
{
IDbConnection _conn;
IDbTransaction _tran;
public TransactedConnection(IDbConnection conn, IDbTransaction tran)
{
_conn = conn;
_tran = tran;
}
public string ConnectionString { get { return _conn.ConnectionString; } set { _conn.ConnectionString = value; } }
public int ConnectionTimeout { get { return _conn.ConnectionTimeout; } }
public string Database { get { return _conn.Database; } }
public ConnectionState State { get { return _conn.State; } }
public IDbTransaction BeginTransaction(IsolationLevel il)
{
throw new NotImplementedException();
}
public IDbTransaction BeginTransaction()
{
return _tran;
}
public void ChangeDatabase(string databaseName)
{
_conn.ChangeDatabase(databaseName);
}
public void Close()
{
_conn.Close();
}
public IDbCommand CreateCommand()
{
// The command inherits the "current" transaction.
var command = _conn.CreateCommand();
command.Transaction = _tran;
return command;
}
public void Dispose()
{
_conn.Dispose();
}
public void Open()
{
_conn.Open();
}
}
#if POSTGRESQL #if POSTGRESQL
class Cat class Cat
......
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