Поиск без учета регистра, не дающий результата - PullRequest
0 голосов
/ 13 ноября 2018

Я не понимаю, почему я не получаю никаких результатов от метода ниже:

    protected async Task<TEntity> GetAsync(string friendlyName, Func<IQueryable<TEntity>, IQueryable<TEntity>> includes = null)
    {
        return await (includes == null
                ? GetAllCurrent()
                : includes(GetAllCurrent()))
            .SingleOrDefaultAsync(e => e.FriendlyName == friendlyName);
    }

При проверке с помощью SQL Server Profiler я вижу, что выполняется следующее:

exec sp_executesql N'SELECT [entity].[Id], [entity].[AgroRangeMultiplier], [entity].[AttackRange], [entity].[CastAreaId], [entity].[ClassId], [entity].[CreatedOnUtc], [entity].[CurrentId], [entity].[EffectId], [entity].[EnergyCost], [entity].[FriendlyName], [entity].[MaxVelocity], [entity].[PreAttackDelay], [entity].[Range], [entity].[RarityId], [entity].[StatusEffectId], [entity].[ThemeId], [entity].[TimeInBetweenAttacksSec], [entity].[TimeToReachMaxVelocitySec], [entity].[UnlockedAtRank], [entity].[UpdatedOnUtc], [entity].[VersionComment], [entity].[Id], [entity].[Name_De], [entity].[Name_En], [entity].[Name_Es], [entity].[Name_Fr], [entity].[Name_It], [entity].[Name_Ja], [entity].[Name_Ko], [entity].[Name_Pl], [entity].[Name_Pt], [entity].[Name_Ru], [entity].[Name_Tr], [entity].[Name_Zh], [entity].[Id], [entity].[DescriptionOnCard_De], [entity].[DescriptionOnCard_En], [entity].[DescriptionOnCard_Es], [entity].[DescriptionOnCard_Fr], [entity].[DescriptionOnCard_It], [entity].[DescriptionOnCard_Ja], [entity].[DescriptionOnCard_Ko], 
[entity].[DescriptionOnCard_Pl], [entity].[DescriptionOnCard_Pt], [entity].[DescriptionOnCard_Ru], [entity].[DescriptionOnCard_Tr], [entity].[DescriptionOnCard_Zh], [entity].[Id], [entity].[DescriptionMarkdown_De], 
[entity].[DescriptionMarkdown_En], [entity].[DescriptionMarkdown_Es], [entity].[DescriptionMarkdown_Fr], [entity].[DescriptionMarkdown_It], [entity].[DescriptionMarkdown_Ja], [entity].[DescriptionMarkdown_Ko], 
[entity].[DescriptionMarkdown_Pl], [entity].[DescriptionMarkdown_Pt], [entity].[DescriptionMarkdown_Ru], [entity].[DescriptionMarkdown_Tr], [entity].[DescriptionMarkdown_Zh], [entity.CastArea].[Id], 
[entity.CastArea].[CreatedOnUtc], [entity.CastArea].[CurrentId], [entity.CastArea].[FriendlyName], [entity.CastArea].[UpdatedOnUtc], [entity.CastArea].[VersionComment], [entity.CastArea].[Id], [entity.CastArea].[Name_De], 
[entity.CastArea].[Name_En], [entity.CastArea].[Name_Es], [entity.CastArea].[Name_Fr], [entity.CastArea].[Name_It], [entity.CastArea].[Name_Ja], [entity.CastArea].[Name_Ko], [entity.CastArea].[Name_Pl], 
[entity.CastArea].[Name_Pt], [entity.CastArea].[Name_Ru], [entity.CastArea].[Name_Tr], [entity.CastArea].[Name_Zh], [entity.StatusEffect].[Id], [entity.StatusEffect].[CreatedOnUtc], [entity.StatusEffect].[CurrentId], 
[entity.StatusEffect].[FriendlyName], [entity.StatusEffect].[UpdatedOnUtc], [entity.StatusEffect].[VersionComment], [entity.StatusEffect].[Id], [entity.StatusEffect].[Name_De], [entity.StatusEffect].[Name_En], 
[entity.StatusEffect].[Name_Es], [entity.StatusEffect].[Name_Fr], [entity.StatusEffect].[Name_It], [entity.StatusEffect].[Name_Ja], [entity.StatusEffect].[Name_Ko], [entity.StatusEffect].[Name_Pl], 
[entity.StatusEffect].[Name_Pt], [entity.StatusEffect].[Name_Ru], [entity.StatusEffect].[Name_Tr], [entity.StatusEffect].[Name_Zh], [entity.Effect].[Id], [entity.Effect].[CreatedOnUtc], [entity.Effect].[CurrentId], 
[entity.Effect].[FriendlyName], [entity.Effect].[UpdatedOnUtc], [entity.Effect].[VersionComment], [entity.Effect].[Id], [entity.Effect].[Name_De], [entity.Effect].[Name_En], [entity.Effect].[Name_Es], [entity.Effect].[Name_Fr], [entity.Effect].[Name_It], [entity.Effect].[Name_Ja], [entity.Effect].[Name_Ko], [entity.Effect].[Name_Pl], [entity.Effect].[Name_Pt], [entity.Effect].[Name_Ru], [entity.Effect].[Name_Tr], [entity.Effect].[Name_Zh], [entity.Class].[Id], [entity.Class].[CreatedOnUtc], [entity.Class].[CurrentId], [entity.Class].[FriendlyName], [entity.Class].[UpdatedOnUtc], [entity.Class].[VersionComment], [entity.Class].[Id], [entity.Class].[Name_De], [entity.Class].[Name_En], [entity.Class].[Name_Es], [entity.Class].[Name_Fr], [entity.Class].[Name_It], [entity.Class].[Name_Ja], [entity.Class].[Name_Ko], [entity.Class].[Name_Pl], [entity.Class].[Name_Pt], [entity.Class].[Name_Ru], [entity.Class].[Name_Tr], [entity.Class].[Name_Zh], [entity.Rarity].[Id], [entity.Rarity].[CreatedOnUtc], [entity.Rarity].[CurrentId], [entity.Rarity].[FriendlyName], [entity.Rarity].[UpdatedOnUtc], [entity.Rarity].[VersionComment], [entity.Rarity].[Id], [entity.Rarity].[Name_De], [entity.Rarity].[Name_En], [entity.Rarity].[Name_Es], [entity.Rarity].[Name_Fr], [entity.Rarity].[Name_It], 
[entity.Rarity].[Name_Ja], [entity.Rarity].[Name_Ko], [entity.Rarity].[Name_Pl], [entity.Rarity].[Name_Pt], [entity.Rarity].[Name_Ru], [entity.Rarity].[Name_Tr], [entity.Rarity].[Name_Zh], [entity.Theme].[Id], [entity.Theme].[CreatedOnUtc], [entity.Theme].[CurrentId], [entity.Theme].[FriendlyName], [entity.Theme].[UpdatedOnUtc], [entity.Theme].[VersionComment], [entity.Theme].[Id], [entity.Theme].[Name_De], [entity.Theme].[Name_En], [entity.Theme].[Name_Es], [entity.Theme].[Name_Fr], [entity.Theme].[Name_It], [entity.Theme].[Name_Ja], [entity.Theme].[Name_Ko], [entity.Theme].[Name_Pl], [entity.Theme].[Name_Pt], [entity.Theme].[Name_Ru], [entity.Theme].[Name_Tr], [entity.Theme].[Name_Zh]
FROM [Card] AS [entity]
INNER JOIN [CardCastArea] AS [entity.CastArea] ON [entity].[CastAreaId] = [entity.CastArea].[Id]
LEFT JOIN [CardStatusEffect] AS [entity.StatusEffect] ON [entity].[StatusEffectId] = [entity.StatusEffect].[Id]
LEFT JOIN [CardEffect] AS [entity.Effect] ON [entity].[EffectId] = [entity.Effect].[Id]
INNER JOIN [CardClass] AS [entity.Class] ON [entity].[ClassId] = [entity.Class].[Id]
INNER JOIN [Rarity] AS [entity.Rarity] ON [entity].[RarityId] = [entity.Rarity].[Id]
INNER JOIN [CardTheme] AS [entity.Theme] ON [entity].[ThemeId] = [entity.Theme].[Id]
WHERE [entity].[FriendlyName] = @__friendlyName_0
ORDER BY [entity].[Id]',N'@__friendlyName_0 nvarchar(450)',@__friendlyName_0=N'stanofmanymoons'

Обратите внимание, что фильтрация выполняется на уровне базы данных с WHERE [entity].[FriendlyName] = @__friendlyName_0

Если я передам FriendlyName с правильным верблюжьим корпусом, возвращаемое значение будет правильным.

При выполнении оператора sql в SSMS я получаю искомое значение, но оно НЕ возвращается EF:

790992AD-D8CE-4ECB-B552-B4BDA5BCDD75    3.33    0.6 E7CCBCBD-024C-4EF0-9126-4F5E62E83A5F    7C15DABB-FDDC-44B1-AC6A-6DE268A3DF00    2018-11-13 08:21:44.9400000 790992AD-D8CE-4ECB-B552-B4BDA5BCDD75    134DFCC4-5867-47A3-80A4-4D560452538A    4   StanOfManyMoons 0.675   0   0.6 D4A7E01F-C1BB-431C-8687-B4946345DB29    NULL    4AF29C4A-282A-4FB8-8691-9D44398A97F2    0.5 0.1 5   2018-11-13 08:21:44.9400000 Initial creation by seeder  790992AD-D8CE-4ECB-B552-B4BDA5BCDD75    NULL    Stan of Many Moons  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    790992AD-D8CE-4ECB-B552-B4BDA5BCDD75    NULL    Charged: Casts a fiery blast at all enemies.    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    790992AD-D8CE-4ECB-B552-B4BDA5BCDD75    NULL    Stan of many Moons is a 4-cost fighter from the Adventure theme who is available at rank 5 that deals damage to all enemy units on the battlefield with his effect. NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    E7CCBCBD-024C-4EF0-9126-4F5E62E83A5F    2018-11-13 08:21:43.7533333 E7CCBCBD-024C-4EF0-9126-4F5E62E83A5F    OwnSide 2018-11-13 08:21:43.7533333 Initial creation by seeder  E7CCBCBD-024C-4EF0-9126-4F5E62E83A5F    NULL    Own Side    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    134DFCC4-5867-47A3-80A4-4D560452538A    2018-11-13 08:21:38.6466667 134DFCC4-5867-47A3-80A4-4D560452538A    Charged 2018-11-13 08:21:38.6466667 Initial creation by seeder  134DFCC4-5867-47A3-80A4-4D560452538A    NULL    Charged NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    7C15DABB-FDDC-44B1-AC6A-6DE268A3DF00    2018-11-13 08:21:37.2100000 7C15DABB-FDDC-44B1-AC6A-6DE268A3DF00    Fighter 2018-11-13 08:21:37.2100000 Initial creation by seeder  7C15DABB-FDDC-44B1-AC6A-6DE268A3DF00    NULL    Fighter NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    D4A7E01F-C1BB-431C-8687-B4946345DB29    2018-11-13 08:21:36.9700000 D4A7E01F-C1BB-431C-8687-B4946345DB29    Legendary   2018-11-13 08:21:36.9700000 Initial creation by seeder  D4A7E01F-C1BB-431C-8687-B4946345DB29    NULL    Legendary   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    4AF29C4A-282A-4FB8-8691-9D44398A97F2    2018-11-13 08:21:41.2266667 4AF29C4A-282A-4FB8-8691-9D44398A97F2    Adventure   2018-11-13 08:21:41.2266667 Initial creation by seeder  4AF29C4A-282A-4FB8-8691-9D44398A97F2    NULL    Adventure   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

Если я адаптирую код к:

.SingleOrDefaultAsync(e => string.Equals(e.FriendlyName, friendlyName, StringComparison.InvariantCultureIgnoreCase))

Результат, возвращаемый методом, является правильным, но все объекты загружаются, и SingleOrDefault выполняется в памяти (чего я абсолютно хочу избежать).

Параметры сортировки БД не чувствительны к регистру (SQL_Latin1_General_CP1_CI_AS).

Теперь к вопросам:
- Как сделать этот запрос нечувствительным к регистру при выполнении фильтрации на уровне базы данных (предложение WHERE)
- Почему мой код не работает? Кажется, сгенерированный SQL-запрос корректен, но EF выполняет дополнительную фильтрацию в памяти, где применяет сравнение с учетом регистра.

...