Reputation: 25
I have a model that contains the id of the current user, every after create/edit the user it includes its id
Model code:
public class Document
{
public int Id { get; set; }
[Required, StringLength(2)]
public string DocumentCode { get; set; }
public string DocumentName { get; set; }
public DateTime DateUpdated { get; set; } = DateTime.Now;
//Id of the current logged user
public string UpdatedBy { get; set; }
}
Controller code:
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,DocumentCode,DocumentName")] Document document)
{
if (id != document.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
document.UpdatedBy = _userManager.GetUserAsync(HttpContext.User).Id.ToString();
_context.Update(document);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!DocumentExists(document.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(document);
}
Error after Edit more than twice.
InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()
How can I possibly fix this issue? First click is ok, but second is not. The error both occurs in Create and Edit function.
Upvotes: 0
Views: 1836
Reputation: 7475
You should call it with await keyword:
document.UpdatedBy = (await _userManager.GetUserAsync(HttpContext.User)).Id.ToString();
In simple words when you call an async method without async keyword your code doesn't wait for the asynchronous GetUserAsync method to finish. So it keeps running when you call the next method but your data is not ready yet.
https://learn.microsoft.com/en-us/dotnet/csharp/async
Upvotes: 1
Reputation: 8539
Suppose, that GetUserAsync
returns Task<User>
object, then it should be awaited first. Then access its properties.
document.UpdatedBy = await (_userManager.GetUserAsync(HttpContext.User)).Id.ToString();
Will be better to check for null here.
document.UpdatedBy = await (_userManager.GetUserAsync(HttpContext.User))?.Id.ToString() ?? string.empty;
Upvotes: 1