问题
I need to update a table of my ApplicationDbContext within a Task; however, I'm not getting it done. Here is the error message I've got:
ex.Message = "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...
I understand it has something to do with threading which I'm not so familiar.
Here's the code:
[HttpPost]
public ActionResult WebHook([FromBody] BotRequest data)
{
Task.Factory.StartNew(() =>
{
//Read value from Table
ContextWatsonFB contextWatsonFB = _context.ContextWatsonFB.Where(m => m.RecipientId == recipientid).FirstOrDefault();
if (contextWatsonFB == null)
{
contextWatsonFB = new ContextWatsonFB()
{
RecipientId = recipientid
};
_context.Add(contextWatsonFB);
_context.SaveChanges();
}
else
{
if (!string.IsNullOrEmpty(contextWatsonFB.Context))
{
model = JsonConvert.DeserializeObject<Context>(contextWatsonFB.Context);
}
}
///DO SOME STUFF ////////////////
///Here I need to update my table using some values processed above in "some stuff"
ContextWatsonFB contextWatsonFB = _context.ContextWatsonFB.Where(m => m.RecipientId == recipientid).FirstOrDefault();
contextWatsonFB.Context = JsonConvert.SerializeObject(context);
_context.Update(contextWatsonFB);
_context.SaveChanges();
}
}
As you can figure it out, its a webhook connection for Facebook, which requires the process to be handled in a Task. Within "some stuff", basically I'm consuming IBM Watson Conversation service whom persist a conversation "context" that I'm not able to send back and forth to Facebook, that's why I figure it out to persist such data in a table to keep the differences among multiple request from facebook messenger.
回答1:
Luckily, the following code did the trick:
private readonly IServiceProvider _provider;
public FacebookBotController(ApplicationDbContext context, IServiceProvider provider)
{
_provider = provider;
}
[HttpPost]
public ActionResult WebHook([FromBody] BotRequest data)
{
if (data == null || data?.entry?.Count == 0)
{
return new StatusCodeResult(StatusCodes.Status204NoContent);
}
try
{
var task = Task.Factory.StartNew(async () =>
{
using (IServiceScope scope = _provider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
ApplicationDbContext _contx = _provider.GetService<ApplicationDbContext>();
ContextWatsonFB contextWatsonFB = await _contx.ContextWatsonFB.Where(m => m.SenderId == senderId).FirstOrDefaultAsync();
if (contextWatsonFB == null)
{
context = null;
}
else
{
context = JsonConvert.DeserializeObject<Context>(contextWatsonFB.Context);
}
}
}
}
来源:https://stackoverflow.com/questions/46333707/task-factory-starnew-and-applicationdbcontext-update