String.Format with SQL wildcard causing Dapper query to break

c# dapper sql string-formatting

Question

I'm having a bit of an odd problem with Dapper and string formatting. Here's the relevant code:

string end_wildcard = @"
SELECT * FROM users
WHERE (first_name LIKE CONCAT(@search_term, '%') OR last_name LIKE CONCAT(@search_term, '%'));";

string both_wildcards = @"
SELECT * FROM users
WHERE (first_name LIKE CONCAT('%', @search_term, '%') OR last_name LIKE CONCAT('%', @search_term, '%'));";

string formatted = @"
SELECT * FROM users
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 = "blah"; // the term the user searched for

// Using Dapper
db.Query(end_wildcard, new{ search_term = term}); // Works and returns results
db.Query(both_wildcards, new{ search_term = term}); // Works and returns results
db.Query(query, new{ search_term = term}); // Returns nothing

The first two queries, where the CONCAT statements with wildcards in them are baked into the string, work perfectly. However, if I take the CONCAT statements out and inject one or the other using String.Format, I get 0 results.

The oddest part of it is that I can debug it, grab the actual query string it uses, put it into MySQL and run it with a @search_term parameter set, and get results while it's paused. Let the code continue, and I get 0 results. Literally the only thing that is different is that one is a pre-compiled string, and the other uses String.Format.

Are '@' and '%' considered special characters by String.Format, or is something else I'm not seeing going on here? The formatted string is literally byte-for-byte equal to one of the two non-formatted strings, and again, pasting it into MySQL actually gives results from the formatted string. Dapper just seems to like two, and not the third, even when it's exactly equal to one of the first two.

Accepted Answer

Please indicate exactly what your query and term are in the example that is failing. I cannot reproduce any issue here. If I use the code as posted, query is identical to end_wildcard, and: it works fine. In a local test rig (with some invented data), I have:

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);

If you are seeing something different, I can only conclude that it must relate to your specific example.

But to be specific:

Are '@' and '%' considered special characters by String.Format, or is something else I'm not seeing going on here?

Nope; string.Format only cares about things like {n} (for integer n), and {{ / }} (which are escape sequences for { and } respectively).

Basically, I find it unlikely that dapper is doing anything related to this, but showing your exact query and term, as they appear when it is failing would help.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why