Я пишу запрос для службы репозитория для таблицы инвентаризации. К вашему сведению: мы используем C # 7.0, EF 6, и мы используем Moq для тестирования наших запросов.
Я узнал, что когда string.Contains(...)
, который по умолчанию чувствителен к регистру, помещается в запрос LINQ, а затем конвертируется в SQL, в результате получается регистр в (найдены другие сообщения SO, чтобы помочь с это, и мы будем иметь дело с этим), и я также обнаружил, что функции string.Contains(...)
, кажется, имеют причуду, когда аргумент string.Empty
и преобразуется в нижний регистр (найдено нет SO сообщения о это).
Попытки использовать строку без учета регистра. Перегрузки Contains (...) отбрасываются с исключением, когда LINQ to Entities пытается преобразовать в SQL, поэтому я должен вручную указать column.Contains(argument.ToLower())
, чтобы оба SQL-запрос LINQ to Entities для работы по назначению и для смоделированного модульного теста на нечувствительность к регистру.
Проблема: Если аргумент является строкой. Пусто, ничего не найдено. Преступник - это когда аргумент преобразуется в нижний регистр.
Это не препятствие (простое перемещение проверки argument.ToLower()
за пределы запроса решило проблему, и в любом случае это было бы немного более эффективно), но я все еще хочу знать, в чем дело.
public List<InventoryModel> FindByTrackingNumberSubstring( string substring )
{
// (bad) matches nothing when argument is string.Empty
//var query = _modelTable.Where( entity => entity.Tracking_Number.ToLower().Contains( substring.ToLower() ) );
// (good) matches everything when argument is string.Empty
string lower = substring.ToLower();
var query = _modelTable.Where( entity => entity.Tracking_Number.ToLower().Contains( lower ) );
return query.ToList<InventoryModel>();
}
// SQL for queries 1 and 2, respectively (stripped out SELECT and FROM stuff for brevity)
WHERE ((CASE WHEN (( CAST(CHARINDEX(LOWER(@p__linq__0), LOWER([Extent1].[Tracking Number])) AS int)) > 0) THEN cast(1 as bit) WHEN ( NOT (( CAST(CHARINDEX(LOWER(@p__linq__0), LOWER([Extent1].[Tracking Number])) AS int)) > 0)) THEN cast(0 as bit) END) = 1)
WHERE ((CASE WHEN (LOWER([Extent1].[Tracking Number]) LIKE @p__linq__0 ESCAPE N'~') THEN cast(1 as bit) WHEN ( NOT (LOWER([Extent1].[Tracking Number]) LIKE @p__linq__0 ESCAPE N'~')) THEN cast(0 as bit) END) = 1)
Я провел некоторую проверку и обнаружил, что в SQL-запросе LINQ to Entities это string.Contains(string.Empty)
соответствует чему угодно, и я обнаружил, что string.Empty.ToLower() == string.Empty
соответствует чему угодно, но соедините их вместе, а C # и LINQ to Entities расходятся. В первом случае string.Contains(string.Empty.ToLower())
соответствует чему-либо (как и ожидалось), но во втором ничего не соответствует ..
Почему?