Как выполнить метод после return в web api?

327
06 июня 2018, 12:50

Код, который должен создать объект, отправить id, а затем обработать в бд. Проблема в том, что я не понимаю как Сначала вернуть ответ, а уже потом работать с этим объектом в БД.

// POST /task
    [HttpPost]
    public IActionResult Post([FromBody]string value)
    {
        Task task = new Task { Id = Guid.NewGuid(), Status = "created", Time = DateTime.Now };
        db.Tasks.Add(task);
        db.SaveChanges();
        //await WaitTwoMinutesAndFinish();
        System.Threading.Tasks.Task t = new System.Threading.Tasks.Task(() => 
        {
            using (db)
            {
                var result = db.Tasks.SingleOrDefault(x => x.Id == task.Id);
                if (result != null)
                {
                    result.Status = "running";
                    result.Time = DateTime.Now;
                    db.SaveChanges();
                }
                //else
                //return 1;
                Thread.Sleep(3000);
                // status = finished
                result.Status = "finished";
                result.Time = DateTime.Now;
                db.SaveChanges();
            }
        });
        t.Start();
        //UpdateRecord(task);
        return Accepted(task.Id);
    }

Но когда я отсылаю запрос, то вылетает исключение (в строке var result):

Cannot access a disposed object. 
A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. 
This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. 
If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Answer 1

Если не интересоваться, зачем это вообще нужно, то можно написать вот такой метод

private async Task MyMethod(int taskId)
{
    using (var db = new MyDbContext())
    {
        var result = await db.Tasks.SingleOrDefaultAsync(x => x.Id == task.Id);
        if (result != null)
        {
            result.Status = "running";
            result.Time = DateTime.Now;
            await db.SaveChangesAsync();
        }
        //else
        //return 1;
        await Task.Delay(3000);
        // status = finished
        result.Status = "finished";
        result.Time = DateTime.Now;
        await db.SaveChangesAsync();
    }   
}

и вызвать его из вашего кода так

MyMethod(task.Id)

Это не создаст нового треда и должно отработать. Но зачем вообще это делать мне не ясно.

Чтобы иметь возможность создать контекст данных, можно прокинуть сервис провайдер, который является контейнером по умолчанию. Пример как это делать:

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private IServiceProvider _serviceProvider;
    public ValuesController(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        Foo();
        return new string[] { "value1", "value2" };
    }     
    private async void Foo()  
    {
        using(var db = (MyDataContext)_serviceProvider.GetService(typeof(MyDataContext)))
        {
            await db.SaveChangesAsync();
        }
    }
}
READ ALSO
Как в ListBox (WPF) добавить иконку?

Как в ListBox (WPF) добавить иконку?

Есть ListBox в который выводится список папок и файловКак в каждый item добавить маленькую иконку (как в Total Commander например)? По сути не понимаю...

301
c#. Как реализовать ожидание выполнения функции?

c#. Как реализовать ожидание выполнения функции?

Имеется такой цикл с подпиской на событие:

335
Ошибка 6002, 6013, 6005 Entity Framework

Ошибка 6002, 6013, 6005 Entity Framework

Что можно сделать с ошибками такого рода или как их полечить? Код в базе менять нельзя

285
Как подключить mySQL к Python 3.6? [закрыт]

Как подключить mySQL к Python 3.6? [закрыт]

Уже насмотрелся разных видео по работе с субдНо ничего толкового так и не нашёл

256