문제

SQL Server에서 Azure 대기열에 레코드를로드하는 것을 작성했습니다. 선택 결과의 항목의 수는 매우 크게 될 수 있으므로 데이터가 계속 검색되는 동안 큐를 시작하고 싶습니다.

EF6 (Async), 모든 Async 메소드 및 tpl ™ quequeueing. 그래서 나는 가지고 있습니다 :

        // This defines queue that Generator will publsh to and 
        // QueueManager wil read from. More info:
        // http://msdn.microsoft.com/en-us/library/hh228601(v=vs.110).aspx
        var queue = new BufferBlock<ProcessQueueItem>();

        // Configure queue listener first
        var result = this.ReceiveAndEnqueue(queue);

        // Start generation process
        var tasks = generator.Generate(batchId);
.

receiveandenqueue는 간단합니다 :

    private async Task ReceiveAndEnqueue(ISourceBlock<ProcessQueueItem> queue)
    {
        while (await queue.OutputAvailableAsync())
        {
            var processQueueItem = await queue.ReceiveAsync();
            await this.queueManager.Enqueue(processQueueItem);
            this.tasksEnqueued++;
        }
    }
.

생성기 생성 () 서명은 다음과 같습니다.

public void Generate(Guid someId, ITargetBlock<ProcessQueueItem> target)
.

대상의 sendasync () 메소드를 호출하여 새 항목을 배치합니다. 내가 지금하고있는 일은 총 결과 수를 '배치'로 나누고, 그대로로드하고, 모든 것을 수행 할 때까지 모든 것을 수행합니다.

    public void Generate(Guid batchId, ITargetBlock<ProcessQueueItem> target)
    {
        var accountPromise = this.AccountStatusRepository.GetAccountsByBatchId(batchId.ToString());
        accountPromise.Wait();
        var accounts = accountPromise.Result;

        // Batch configuration
        var itemCount = accounts.Count();
        var numBatches = (int)Math.Ceiling((double)itemCount / this.batchSize);
        Debug.WriteLine("Found {0} items what will be put in {1} batches of {2}", itemCount, numBatches, this.batchSize); 


        for (int i = 0; i < numBatches; i++)
        {
            var itemsToTake = Math.Min(this.batchSize, itemCount - currentIndex);
            Debug.WriteLine("Running batch - skip {0} and take {1}", currentIndex, itemsToTake);

            // Take a subset of the items and place them onto the queue
            var batch = accounts.Skip(currentIndex).Take(itemsToTake);

            // Generate a list of tasks to enqueue the items
            var taskList = new List<Task>(itemsToTake);
            taskList.AddRange(batch.Select(account => target.SendAsync(account.AsProcessQueueItem(batchId))));

            // Return the control when all tasks have been enqueued
            Task.WaitAll(taskList.ToArray());

            currentIndex = currentIndex + this.batchSize;
        } 
.

이 작동하지만, 동료는 "인터페이스를 더 간단하게 만들 수 없으며, 생성 ()을 만들고 인터페이스를 만들 수 없습니다 :

public Task<IEnumerable<ProcessQueueItem> Generate(Guid someId)
.

롯트 클리너 및 TPL 라이브러리에 생성 된 메소드의 종속성이 없습니다. 나는 완전히 동의한다, 나는 그 일을한다면, 나는 전화를 걸어라고

라고 할 것이다.
var result = Generate().Wait().Result;
.

어떤 시점에서 모든 항목에 enqueuinig 전에. 그 모든 것들이 모든 물건이로드되고 메모리에있는 모든 것들을 기다릴 것입니다.

내 질문이 내려 오는 것은 다음과 같습니다. 선택에서 똑똑한 '숫자가 묻는 것처럼 ef 쿼리 결과를 사용할 수 있습니까? EF가 내 드리프트를 잡을 경우 결과를 통해 'yield'를 실행할 것입니다.

편집 나는 생각 실수를했다고 생각합니다. EF는 기본적으로 게으른 항목을로드합니다. 그래서 모든 결과를 iQueryable <>로 반환 할 수는 있지만 실제로 DB에서로드 된 것을 의미하지는 않습니다. 그런 다음 그런 다음 그들을 반복하고 그들을 대기합니다.

편집 2 Nope, 생성되지 않기 때문에 생성되지 않고 생성 된 () 메서드에서 개체를 데이터베이스에서 변환해야합니다 ...

도움이 되었습니까?

해결책

확인, 이것은 내가 끝난 것입니다 :

    public IEnumerable<ProcessQueueItem> Generate(Guid batchId)
    {
        var accounts = this.AccountStatusRepository.GetAccountsByBatchId(batchId.ToString());

        foreach (var accountStatuse in accounts)
        {
            yield return accountStatuse.AsProcessQueueItem(batchId);
        }
    }
.

리포지토리는 일부 DataContext.stuff.where (...)의 iEnumerable을 반환합니다.발전기는 확장 메소드를 사용하여 QueueManager를 시작하기 위해 QueueManager를 호출하기 시작하여 수율의 호출자로 즉시 도메인 모델 (ProcessQueueItem)으로 엔티티를 도메인 모델 (ProcessQueueItem)으로 변환합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top