DbContext отслеживает изменения в объектах, которые обрабатываются в других потоках - PullRequest
1 голос
/ 23 сентября 2019

Я работаю с отсоединенными объектами и отправляю их в конвейер TPL DataFlow.Первая проблема TransformBlock.

. Это происходит, когда я увеличиваю параллелизм TransformBlock до значения, превышающего 1. Я не наблюдал проблем при тестировании с максимальной степенью параллелизма =1.

Объект ввода и вывода TransformBlock является документом.Цель этого состоит в том, чтобы сделать некоторые вызовы API, обновить объект документа, сохранить его в базе данных и вернуть его для дальнейшей обработки в конвейере.

// MaxDegreeOfParallelism = 20
DocumentCreationTransformBlock = new TransformBlock<Document, Document>(async document =>
{                                                      
    await _createDocumentAction.DoCreateActionAsync(document);                       
    return document;
});

Метод DoCreateActionAsync создает новый DbContext и вручную контролирует присоединение объектов и обновление измененных свойств.

// pass in a document object which is an Entity object but is 'disconnected' (no tracked changes)
public async Task<bool> DoCreateActionAsync(Document document)
{
    // Make some changes to the detached 'document' object properties
    document.Attempt++;

    // make the REST API call 
    await CreateAsync(document);

    document.Result = 1;
    document.NewId = '1111100000';

    using (MyEntities context = new MyEntities())
    {
        // 1. Attach the document to this context. It attaches with the EntityState = Unchanged.
        context.Documents.Attach(document);

        // 2. Manually set properties we know we have edited to IsModified = true
        context.Entry(document).Property(u => u.Attempt).IsModified = true;
        context.Entry(document).Property(u => u.Result).IsModified = true;
        context.Entry(document).Property(u => u.NewId).IsModified = true;

        // 3. Updated version 1 in the collection navigation property DocumentVersions
        // DocumentVersions have previously been Eagerly Loaded, so no database query occurs here.
        var version1 = document.DocumentVersions.OrderBy(v => v.DocumentVersion).FirstOrDefault(); 
        if (version1 != null)
        {
            context.Entry(version1).Property(u => u.VersionCreated).IsModified = true;
        }            

        context.SaveChanges();
    }
}

Из приведенного выше кода я ожидаю, что вызов SaveChanges() сгенерирует:

  • 1 SQLОператор обновления для объекта Document

  • 1 Оператор обновления SQL для объекта DocumentVersion

Я вывел объекты из списка DBContext.ChangeTracker.Entries(), которыеизменяются вместе с любыми измененными свойствами.

В этом примере я обновлял Document id = 8 (и связанный с ним DocumentVersion id = 12)

#EntityType - #EntityState - #EntityKey
Document - Modified - Id:3
    Result
    NewId
Document - Modified - Id:8
    Attempt
    Result
    NewId
DocumentVersion - Modified - Id:6
    VersionCreated
DocumentVersion - Modified - Id:12
    VersionCreated

Объект, который я хочу обновить, всегда обновлялся, но случайным образом (разные результатыпри каждом запуске теста) обновлялись дополнительные документы.

Я перезапускал код, и каждый раз при этом влияли на разные документы.Иногда до 3 документов находятся в списке отслеживания изменений.Единственная постоянная вещь - как минимум, сущности, которые я хочу отслеживать, отслеживаются.Отслеживаемые здесь «дополнительные» сущности также обновляются в разных потоках по мере их передачи в метод DoCreateActionAsync.

Как дополнительные сущности присоединяются к этому DbContext?

...