2

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.

4

1 に答える 1

1

失敗している例であなたのとが何であるかを正確に示してください。ここで問題を再現することはできません。投稿されたコードを使用すると、と同じで、正常に動作します。ローカルテストリグ(いくつかの発明されたデータを使用)では、次のものがあります。querytermqueryend_wildcard

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

何か違うものを見ている場合、それはあなたの特定の例に関連しているに違いないと結論付けることができます.

しかし、具体的に言うと:

'@' と '%' は String.Format によって特殊文字と見なされますか、それともここで起こっていないことはありますか?

いいえ; ( integer の場合) や/ (それぞれおよびのエスケープ シーケンス) のstring.Formatようなものだけを気にします。{n}n{{}}{}

基本的に、dapper がこれに関連することを行っている可能性は低いと思いますが、失敗したときに表示されるquery正確なとtermを表示すると役立ちます。

于 2013-05-24T07:07:41.297 に答える