Commit 86476bc2 authored by Marc Gravell's avatar Marc Gravell

(courtesy @mrange) fix dictionary semantics of DapperRow

parent eba9780e
......@@ -1327,7 +1327,7 @@ internal bool FieldExists(string key)
sealed partial class DapperRowMetaObject : System.Dynamic.DynamicMetaObject
{
static readonly MethodInfo getValueMethod = typeof(IDictionary<string, object>).GetProperty("Item").GetGetMethod();
static readonly MethodInfo setValueMethod = typeof(DapperRow).GetMethod("SetValue");
static readonly MethodInfo setValueMethod = typeof(DapperRow).GetMethod("SetValue", new Type[] { typeof(string), typeof(object) });
public DapperRowMetaObject(
System.Linq.Expressions.Expression expression,
......@@ -1546,8 +1546,7 @@ IEnumerator IEnumerable.GetEnumerator()
void IDictionary<string, object>.Add(string key, object value)
{
IDictionary<string, object> dic = this;
dic[key] = value;
SetValue(key, value, true);
}
bool IDictionary<string, object>.Remove(string key)
......@@ -1561,9 +1560,14 @@ IEnumerator IEnumerable.GetEnumerator()
object IDictionary<string, object>.this[string key]
{
get { object val; TryGetValue(key, out val); return val; }
set { SetValue(key, value); }
set { SetValue(key, value, false); }
}
public object SetValue(string key, object value)
{
return SetValue(key, value, false);
}
private object SetValue(string key, object value, bool isAdd)
{
if (key == null) throw new ArgumentNullException("key");
int index = table.IndexOfName(key);
......@@ -1571,10 +1575,21 @@ public object SetValue(string key, object value)
{
index = table.AddField(key);
}
if (values.Length <= index)
{ // we'll assume they're doing lots of things, and
else if (isAdd && index < values.Length && !(values[index] is DeadValue))
{
// then semantically, this value already exists
throw new ArgumentException("An item with the same key has already been added", "key");
}
int oldLength = values.Length;
if (oldLength <= index)
{
// we'll assume they're doing lots of things, and
// grow it to the full width of the table
Array.Resize(ref values, table.FieldCount);
for (int i = oldLength; i < values.Length; i++)
{
values[i] = DeadValue.Default;
}
}
return values[index] = value;
}
......
......@@ -378,6 +378,40 @@ public void TestStrings()
.IsSequenceEqualTo(new[] { "a", "b" });
}
// see http://stackoverflow.com/questions/16726709/string-format-with-sql-wildcard-causing-dapper-query-to-break
public void CheckComplexConcat()
{
string end_wildcard = @"
SELECT * FROM #users16726709
WHERE (first_name LIKE CONCAT(@search_term, '%') OR last_name LIKE CONCAT(@search_term, '%'));";
string both_wildcards = @"
SELECT * FROM #users16726709
WHERE (first_name LIKE CONCAT('%', @search_term, '%') OR last_name LIKE CONCAT('%', @search_term, '%'));";
string formatted = @"
SELECT * FROM #users16726709
WHERE (first_name LIKE {0} OR last_name LIKE {0});";
string use_end_only = @"CONCAT(@search_term, '%')";
string use_both = @"CONCAT('%', @search_term, '%')";
// if true, slower query due to not being able to use indices, but will allow searching inside strings
bool allow_start_wildcards = false;
string query = String.Format(formatted, allow_start_wildcards ? use_both : use_end_only);
string term = "F"; // the term the user searched for
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')");
// Using Dapper
connection.Query(end_wildcard, new { search_term = term }).Count().IsEqualTo(2);
connection.Query(both_wildcards, new { search_term = term }).Count().IsEqualTo(3);
connection.Query(query, new { search_term = term }).Count().IsEqualTo(2);
}
enum EnumParam : short
{
None, A, B
......
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