우리는 데이터 계층에 EF 4.3을 사용하고 있으며 일반적인 저장소 패턴을 사용하고 있습니다. 백엔드는 SQL 2008 R2이고 프로젝트는 .NET 4.0/MVC 3이지만이 요소가 문제가되지는 않을 것이라고 생각합니다.EF 4.3 다중 열거 문제
기본적으로 우리는 두 개의 객체로 구성된 데이터베이스에 일대일 관계가 있습니다. 하나는 '함정'을위한 것이고 두 번째는 '함정 활동'을위한 것입니다. 즉, 이러한 '트랩'중 하나가 배포되면 해당 트랩에 발생하는 모든 내용이 트랩 활동 테이블에 보관됩니다. 이 작업을 수행하는 방법은 매우 간단해야합니다.
관계는 '트랩 활동'테이블의 '트랩'테이블의 PK에 대한 FK로 정의됩니다. 두 테이블 모두 PK가 정의되어 있습니다.
서비스 레이어에서 이러한 트랩이 배포 된 날짜가있는 '트랩'목록을 쿼리해야합니다. 이는 다음 코드 스 니펫으로 수행됩니다.
var traps = this.trapRepository.Find(x => x.DeploymentYear == 2012).Select(x => new TrapHomeViewModel
{
County = x.County.Name,
DeploymentDate = x.TrapActivities.First(y => y.ActivityType == 1).ActivityDate,
State = x.County.CountyState.Abbreviation,
Latitude = x.Latitude,
Longitude = x.Longitude,
TrapId = x.TrapID,
TrapNumber = x.SerialNumber,
Centroid = x.TrapCentroid
}).ToList();
문제는 DeploymentDate 속성에서 발생합니다. 서면으로, 이것은 대략 3000의 품목의 명부를 돌려 보내기 위하여 25s를 가지고 간다. 트랩 테이블을 업데이트하여 배포 날짜를 저장하고이 행을 채우십시오.
DeploymentDate = x.DeploymentDate.Value.Date
결과가 1 초 미만입니다.
SELECT Counties.Name, TrapActivities.ActivityDate, States.Abbreviation,
Traps.Latitude, Traps.Longitude, Traps.TrapID, Traps.SerialNumber, Traps.TrapCentroid
FROM TrapActivities INNER JOIN
Traps ON TrapActivities.TrapID = Traps.TrapID INNER JOIN
Counties ON Traps.CountyID = Counties.CountyID INNER JOIN
States ON Counties.State = States.FIPS_Code
WHERE (TrapActivities.ActivityType = 1)
...하지만이 될 것 같지 않습니다 : 지금은 내가 여기에 것입니다 (데이터 세트의 여러 열거)하지만 다음과 유사한 쿼리 될 것 일어날 것이라고 생각했던 것을 알고 있다고 생각 경우. 위의 모든 배경 정보와 함께,이 뷰 모델을 채우는 데 어디서 이탈 했습니까? 이전에이 문제에 부딪혔다 고 생각하지 않지만 이는 다른 프로젝트보다 훨씬 큰 데이터 세트입니다. 이것에 대한 지침은 많은 도움이 될 것입니다. 다른 정보를 제공해야하는 경우 알려 주시기 바랍니다.
EDIT
요청한 바와 같이, GenericRepository 메소드 및 생성자 찾기 : 이것은 상기 코드에 의해 생성되는 SQL의 예
public class GenericRepository<T> : IGenericRepository<T>
where T : class
{
private readonly IObjectSet<T> objectSet;
private ObjectContext context;
public GenericRepository()
: this(new APHISEntities())
{
}
public GenericRepository(ObjectContext context)
{
this.context = context;
this.objectSet = this.context.CreateObjectSet<T>();
}
public IEnumerable<T> Find(Func<T, bool> predicate)
{
return this.objectSet.Where(predicate);
}
EDIT 2
을 :
exec sp_executesql N'SELECT
[Extent1].[TrapActivityID] AS [TrapActivityID],
[Extent1].[TrapID] AS [TrapID],
[Extent1].[ActivityType] AS [ActivityType],
[Extent1].[Notes] AS [Notes],
[Extent1].[AgentID] AS [AgentID],
[Extent1].[ActivityDate] AS [ActivityDate],
[Extent1].[CreatedOn] AS [CreatedOn],
[Extent1].[EditedOn] AS [EditedOn],
[Extent1].[Deleted] AS [Deleted],
[Extent1].[VisualInspectionID] AS [VisualInspectionID]
FROM [dbo].[TrapActivities] AS [Extent1]
WHERE [Extent1].[TrapID] = @EntityKeyValue1',N'@EntityKeyValue1 uniqueidentifier',@EntityKeyValue1='FEBC7ED4-E726-4F5E-B2BA-FFD53AB7DF34'
트랩 ID 목록을 가져 와서 각각에 대해 쿼리를 실행하면 수천 개의 SQL 문이 생성됩니다. 또한 카운티 정보에 대한 개별 쿼리를 실행하는 것처럼 보입니다.
이 상황에서 최선의 선택이되며 미래의 상황에서는 데이터베이스에서 Anjlab SQL 프로파일 러와 같은 프로파일 러를 실행하는 것이 좋습니다. 그것은 실행중인 정확한 SQL과 각 호출에 걸리는 시간을 보여줍니다. 그런 다음 비효율적으로 매우 뛰어난 작업을 수행하는지 확인할 수 있습니다. 속도를 높이려면 데이터베이스에 인덱스를 추가하기 만하면됩니다. 25 초가 걸리는 쿼리를 찾으면 SSMS에 실행 경로를 볼 수있는 옵션이 있으며 문제가있는 위치를 확인해야합니다. – NibblyPig
네트워크 트래픽 (Wire Shark가 수행 할 것입니다)을 잡아서 어떤 쿼리가 생성되는지 정확히 볼 수 있습니다. 그런 다음이를 살펴보고 인덱스를 최적화 할 수 있는지 확인하십시오. 생성하는 쿼리에 놀랄 수도 있습니다. 저는 제 일부와 함께했습니다. – itsmatt
저장소의 '찾기'메소드는 어떻게 생겼습니까? –