Ошибка обновления объекта: вторая операция началась в этом контексте до завершения предыдущей операции - PullRequest
3 голосов
/ 09 октября 2019

Когда я обновляю сущность, я получаю ошибку в контроллере

Вторая операция началась в этом контексте перед завершением предыдущей операции. Ни один из членов экземпляра не гарантированно является потокобезопасным.

Код:

public class MyController: Controller
{
   private readonly DbContext _db = new DbContext();

Метод

[HttpPatch]
[Route("MyRoute")]
public async Task<ActionResult> UpdateMyCase([Required][FromBody]MyProject body)
{
    using(var dbContextTransaction = _db.Database.BeginTransaction())
    {
        _db.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        var p = (from a in _db.MyProject
                 where a.Id == body.Id
                 select a).FirstOrDefault();
        p.Name = "new Name";
        p.Score = "new score";

        // ....
        var m = _db.MyProjectLink.Where(x => x.Id == p.Id);

        for(var key in m)
        {
            if(m.Any(x => x.Id != "something"))
            {
                var link = new MapProjectLink();
                link.MapId = "some id dynamic generated";
                link.Id = body.Id;
                link.Tool = key.tool;
                _db.MapProjectLink.Add(link);
            }
        }

        await _db.SaveChangesAsync();
        return OK(p);
    }
}

Чтобы объяснить код, в основном яесть три стола. _db.MyProject, _ db.MyMap и _db.MapProjectLink. Первые две таблицы много ко многим;и третья таблица связывает их вместе. Я хочу сохранить обновленное значение в двух таблицах: _db.MyProject и _db.MapProjectLink.

Кстати, в данный момент я не использую внедрение зависимостей. Я думаю, что, возможно, цикл for вызывает проблему.

Ошибка:

Исключительная ситуация в базе данных при сохранении изменений для типа контекста 'MapProjectLink'. System.InvalidOperationException: вторая операция началась в этом контексте перед завершением предыдущей операции. Любые члены экземпляра не гарантированно являются потокобезопасными.

Ответы [ 3 ]

1 голос
/ 10 октября 2019

Оказывается, я должен поместить все, что связано с _db, в Task.Run. Тогда Wait. Это означает, что нужно дождаться окончания задания и перейти к следующему потоку.

0 голосов
/ 10 октября 2019

DbContext не является поточно-ориентированным. Вы должны создать новый контекст (вместо того, чтобы повторно использовать один и тот же экземпляр _db для каждой операции базы данных. Это лучший метод даже для однопоточных процессов.

Примечание: именно поэтому, когда вы ждетедля каждой задачи это «работает» - потому что вы больше не обращаетесь к своему контексту из нескольких потоков.

0 голосов
/ 09 октября 2019

Я думаю, что вам не хватает совершить транзакцию в конце .... dbContextTransaction.Commit () после SaveChangesAsync () должна сработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...