Я реализовал плагин twitter typeahead для автозаполнения форм в моем приложении.
При запросе в базе данных совпадения с именем, введенным в поле ввода, оно будет соответствовать только чувствительным к регистру именам, однако предполагается, что typeahead соответствует нечувствительному к регистру.
Пример: напечатанное написание «Кевин С» предполагает Кевина Смита, но напечатанное «Кевин С» ничего не говорит.
Код API
// GET: /api/authors
public IHttpActionResult GetAuthors(string query = null)
{
var authorsQuery = _context.Authors.ToList().Select(Mapper.Map<Author, AuthorDto>);
if (!String.IsNullOrWhiteSpace(query))
authorsQuery = authorsQuery.Where(c => c.Name.Contains(query));
return Ok(authorsQuery);
}
Я думал, что это как-то связано с выполнением .ToList () перед запросом базы данных с помощью моего вызова .Where ().
Я изменил свой код на этот, и теперь он работает
// GET: /api/authors
public IHttpActionResult GetAuthors(string query = null)
{
var authorsQuery = _context.Authors.AsQueryable();
if (!String.IsNullOrWhiteSpace(query))
authorsQuery = authorsQuery.Where(c => c.Name.Contains(query));
var authorsDto = authorsQuery.ToList().Select(Mapper.Map<Author, AuthorDto>);
return Ok(authorsDto);
}
поэтому при вводе "kevin s" напечатанный текст предлагает "Kevin Smith"
Я пробовал использовать AsEnumerable вместо AsQueryable (), и он имел тот же эффект, что и исходный код.
почему он работает с AsQuerable, но не работает с другими? это связано с выполнением запроса?
Прочтите, дайджест, верните: stackoverflow.com/questions/17968469/… Это актуально для очень.
Фильтрация на IQueryable
приведет к изменению выполняемого SQL. Если в вашей базе данных используется регистр вsensitive, ваш запрос тоже будет. Однако, если вы используете IQueryable
в коллекции .NET, а затем фильтруете ее, вы запускаете код .NET, который не подчиняется тем же правилам.
I thought it had something to do with the .ToList() executing before querying the database with my .Where() call.
Ты прав. С .AsQueryable()
ваш c => c.Name.Contains(query)
- это дерево выражений. Это означает, что он не переводится в код MSIL, который запускает то, что вы написали, а переводится в описание того, что вы написали. Entity Framework может использовать это для преобразования в SQL, а в SQL это может быть нечувствительным к регистру, даже если оно будет чувствительным к регистру в обычном коде C#.
.Where
преобразуется в Queryable.Where
.
I tried with AsEnumerable instead of AsQueryable() and it had the same effect as the original code
С .AsEnumerable()
, даже если ваш запрос не выполняется сразу, c => c.Name.Contains(query)
является скомпилирован в обычный код C#.
Это потому, что Queryable.Where
нельзя использовать (у вас нет IQueryable<T>
), а вместо него используется Enumerable.Where
. Последний не принимает деревья выражений.
Спасибо, это отличный ответ. Спасибо и другим за то, что объяснили это по-разному и указали мне на отличный ресурс.
AsQueryable
, вероятно, использует параметры сортировки по умолчанию для вашей базы данных для сравнения, тогда как другие методы запускают код в среде CLR.