2011-01-18 2 views
8

내 Entity Framework 4.0 기반 데이터베이스 계층을 프로파일 링 한 후 주요 성능 죄인을 엔티티가 데이터베이스에 이미 존재하는지 확인하는 데 사용하는 간단한 LINQ Any()로 판별했습니다. Any() 검사는 엔티티를 저장하는 것보다 느린 순서로 수행합니다. 데이터베이스에 비교적 적은 행이 있으며 확인중인 열의 색인이 생성됩니다.Entity Framework에서 LINQ 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에서 코드를 유지하는 것이 좋습니다.

EF로 "Exist"체크를 빨리 할 수있는 방법이 있습니까?

아마도 n 계층 아키텍처에서 자체 추적 엔티티를 사용한다고 언급해야합니다. 일부 시나리오에서는 일부 엔티티의 ChangeTracker 상태가 이미 데이터베이스에 존재하더라도 "추가됨"으로 설정됩니다. 따라서 데이터베이스를 업데이트 할 때 삽입 오류 예외가 발생하면 Check를 사용하여 ChangeTracker 상태를 적절히 변경해야합니다.

답변

0

문제는 Entity Framework (적어도 EF4)가 바보 같은 SQL을 생성한다는 것입니다. 다음 코드는 최소한의 고통으로 적절한 SQL을 생성하는 것으로 보입니다. 심지어

(from sg in context.SettingGroups 
where sg.Group.Equals(settingGroup) && sg.Category.Equals(settingCategory) 
select sg).BetterAny() 

또는 :

public static class LinqExt 
{ 
    public static bool BetterAny<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate) 
    { 
     return queryable.Where(predicate).Select(x => (int?)1).FirstOrDefault().HasValue; 
    } 

    public static bool BetterAny<T>(this IQueryable<T> queryable) 
    { 
     return queryable.Select(x => (int?)1).FirstOrDefault().HasValue; 
    } 

} 

그럼 당신은 할 수

context.SettingGroups.BetterAny(sg => sg.Group.Equals(settingGroup) && sg.Category.Equals(settingCategory)); 
0

나는 비참한 해결책이 들리 겠지만, Any 대신 Count를 사용하면 어떻게 될까요?

+0

나는 그것을 시도를 제공 할 것입니다. – Holstebroe

0

생성 된 select 명령문을 실행할 시간에 대해 프로파일 링하여 예상되는/수행하고자하는 것을 선택하십시오. 보이는 것처럼 나쁘지 않을 수도 있습니다.

섹션

SELECT 
1 AS [C1] 
FROM [dbo].[SettingGroups] AS [Extent1] 
WHERE ([Extent1].[Group] = @p__linq__0) AND ([Extent1].[Category] = @p__linq__1) 

당신이 생산 될 것으로 예상 것이 무엇 아마 가깝습니다. 쿼리 최적화 프로그램은 두 번째 쿼리가 첫 번째 쿼리와 동일하므로 전체 쿼리에 거의 시간을 추가하지 않을 가능성이 높습니다.

1

데이터베이스 테이블 "SettingGroups"에 인덱스를 추가하려면 그룹 & 범주로 시도해보십시오.

현재이 비슷한 sql?

var ok = context.SettingGroups.Any(sg => sg.Group==settingGroup && sg.Category==settingCategory); 
+0

예, 색인을 사용하십시오. SettingGroups (그룹, 범주)에 색인 IX_SettingGroups_GC 작성 – Ben

관련 문제