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

请在失败的示例中准确说明您的query和是什么。term我无法在这里重现任何问题。如果我使用发布的代码,query则与 , 相同end_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 视为特殊字符,还是我在这里看不到的其他内容?

没有; string.Format只关心{n}(对于 integer n)和{{/ (分别是和}}的转义序列)之类的东西。{}

基本上,我发现 dapper 不太可能做与此相关的任何事情,但显示你的确切queryand term因为它们在失败时出现会有所帮助。

于 2013-05-24T07:07:41.297 回答