После профилирования уровня базы данных на основе Entity Framework 4.0 я обнаружил, что основным фактором, влияющим на производительность, является простая функция LINQ Any (), которую я использую, чтобы проверить, существует ли уже сущность в базе данных. Проверка Any () выполняется на несколько порядков медленнее, чем сохранение объекта.
В базе данных относительно мало строк, и проверяемые столбцы индексируются.
Я использую следующий LINQ для проверки существования группы настроек:
from sg in context.SettingGroups
where sg.Group.Equals(settingGroup) && sg.Category.Equals(settingCategory)
select sg).Any()
Это генерирует следующий SQL (кроме того, мой профилировщик SQL утверждает, что запрос выполняется дважды):
exec sp_executesql N'SELECT
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[SettingGroups] AS [Extent1]
WHERE ([Extent1].[Group] = @p__linq__0) AND ([Extent1].[Category] = @p__linq__1)
)) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[SettingGroups] AS [Extent2]
WHERE ([Extent2].[Group] = @p__linq__0) AND ([Extent2].[Category] = @p__linq__1)
)) THEN cast(0 as bit) END AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]',N'@p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000)',@p__linq__0=N'Cleanup',@p__linq__1=N'Mediator'
Прямо сейчас я могу думать только о создании хранимых процедур для решения этой проблемы, но я, конечно, предпочел бы сохранить код в LINQ.
Есть ли способ заставить такую проверку "Exist" работать быстрее с EF?
Я, вероятно, должен упомянуть, что я также использую самоконтрольные сущности в n-уровневой архитектуре. В некоторых сценариях состояние ChangeTracker для некоторых объектов установлено как «Добавлено», даже если они уже существуют в базе данных. Вот почему я использую проверку, чтобы соответствующим образом изменить состояние ChangeTracker, если обновление базы данных вызвало исключение ошибки вставки.