2011-02-28 5 views
26

다른 것들 중에서 쿼리를 입력 할 때 실시간 검색 결과를 사용자에게 전달할 수 있어야하는 WinForms 응용 프로그램 용 쿼리 관리자를 작성하는 중입니다. (웹이 아닌 두꺼운 클라이언트 환경에서도 분명히 Google의 실제 결과를 생각해보십시오.) 검색 결과는 사용자 유형에 따라 도착하기 시작해야하기 때문에 더욱 구체적인 검색이 이루어 지므로 사용자가 더 구체적인 정보를 입력하는 동안 계속 실행중인 경우 쿼리를 취소 할 수 있기를 원합니다 (결과는 어쨌든, 단순히 버려짐).엔터티 프레임 워크 쿼리 취소하기

평범한 ADO.NET이라면 ​​분명히 DbCommand.Cancel 기능을 사용할 수 있지만이 기능을 사용할 수는 있지만 데이터 액세스에는 EF4를 사용하고 있으며 취소 할 수있는 확실한 방법은없는 것 같습니다. 질문. 또한 Reflector의 System.Data.Entity를 열어 EntityCommand.Cancel을 보면 docs에도 불구하고이 메서드를 호출하면 공급자 명령의 해당 Cancel 함수에 전달된다는 주장에도 불구하고 빈 몸체가 빈 것처럼 보입니다.

나는 단순히 기존 쿼리를 실행시키고 새로운 검색을 실행하기 위해 새로운 컨텍스트를 돌리는 것을 고려해 봤지만 (기존 쿼리가 끝나면 기존 쿼리를 삭제하는 것), 나는 하나의 클라이언트에 대한 생각이 싫다. 가장 최근의 결과에만 관심이있을 때 병렬 쿼리를 실행하는 수많은 데이터베이스 연결.

이 모든 것들이 EF 쿼리가 데이터베이스에 전달되면이를 취소 할 수있는 방법이 없다고 생각합니다. 그러나 여기있는 누군가가 간과 한 것을 지적 할 수 있기를 바랍니다.

TL/DR 버전 : 현재 실행중인 EF4 쿼리를 취소 할 수 있습니까?

+0

내가 MSDN 포럼에서이 문제에 대해 질문을했다 : 단순히 현재 쿼리를 중지하는 또 다른 방법은 내부의 열거입니다 http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/ d5ea8036-73e5-4566-9407-fa7a6a5fca3c이 원래 질문은 링크되어 있습니다.MS의 누군가가 다른 솔루션을 제공하기를 바랍니다. –

답변

12

EF에서 버그를 발견 한 것 같지만 MS에보고 할 때 문서에서 버그로 간주됩니다. 어쨌든 나는 EntityCommand과 직접 상호 작용한다는 생각을 좋아하지 않습니다. 여기에 현재 쿼리를 죽일 방법을 내 예입니다 : 그것은 최종 솔루션으로 간주되어야 뭔가 아마 그래서

var thread = new Thread((param) => 
    { 
     var currentString = param as string; 

     if (currentString == null) 
     { 
      // TODO OMG exception 
      throw new Exception(); 
     } 

     AdventureWorks2008R2Entities entities = null; 
     try // Don't use using because it can cause race condition 
     { 
      entities = new AdventureWorks2008R2Entities(); 

      ObjectQuery<Person> query = entities.People 
       .Include("Password") 
       .Include("PersonPhone") 
       .Include("EmailAddress") 
       .Include("BusinessEntity") 
       .Include("BusinessEntityContact"); 
      // Improves performance of readonly query where 
      // objects do not have to be tracked by context 
      // Edit: But it doesn't work for this query because of includes 
      // query.MergeOption = MergeOption.NoTracking; 

      foreach (var record in query 
       .Where(p => p.LastName.StartsWith(currentString))) 
      { 
       // TODO fill some buffer and invoke UI update 
      } 
     } 
     finally 
     { 
      if (entities != null) 
      { 
       entities.Dispose(); 
      } 
     } 
    }); 

thread.Start("P"); 
// Just for test 
Thread.Sleep(500); 
thread.Abort(); 

그것은 경우 30 분 후에 내 연주의 결과입니다. 적어도이 솔루션으로 인해 발생할 수있는 문제에 대한 피드백을 얻으려면 게시하고 있습니다. 주요 포인트는 다음과 같습니다

  • 상황은
  • 결과는 당신이 스레드 쿼리가 종료 죽이면 상황
  • 에 의해 추적되지 않고 문맥 (연결 해제)
  • 당신이 죽이면 배치 스레드 내부에서 처리됩니다 새 스레드를 시작하기 전에 스레드를 계속 연결해야합니다.

SQL 프로파일 러에서 쿼리가 시작되고 종료되었음을 확인했습니다.

편집 : Btw는

.

public IEnumerable<T> ExecuteQuery<T>(IQueryable<T> query) 
{ 
    foreach (T record in query) 
    { 
     // Handle stop condition somehow 
     if (ShouldStop()) 
     { 
      // Once you close enumerator, query is terminated 
      yield break; 
     } 
     yield return record; 
    } 
} 
+0

흥미 롭; 설명의 요점으로 'EntityCommand'와의 상호 작용이 올바른 접근이라고 제안하지는 않았지만 메서드 본문이 비어 있다는 사실은 더 높은 수준에서 가능할 가능성이 희박하다는 것을 의미했습니다. 이것은 흥미로운 시나리오이며 결국에는 효과가있을 수 있지만, 지금 가능한 한 변경 추적이 필요하므로 컨텍스트를 폐기하는 것이 내가 할 준비가되지 않은 것입니다. 내가 대안을 찾을 수 없다면, 나는 이것을 받아 들일 것이다. –

+0

@Adam : Ok, 새로운 결과가 있기 때문에 내일은 변경 추적 시나리오에 대해 생각해 볼 것입니다. 쿼리를 취소하더라도로드 된 모든 인스턴스는 이미 상황에 따라 추적됩니다. 나의 초기 제안은 각 검색에 대한 새로운 맥락이지만 그것에 대해 생각해야합니다. –

+0

로드하는 동안 쿼리를 취소하는 것에 대해서는별로 신경 쓰지 않습니다. 그것은 위와 같은 접근 방식으로 충분히 쉽게 달성됩니다. 내가 찾고있는 것은 * 쿼리 * 단계 (서버 측 실행 중)에서 취소하는 것입니다. –