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.