Quantcast
Channel: ASP.NET Core
Viewing all articles
Browse latest Browse all 9386

How to make DB access thread-safe?

$
0
0

Hi,

I have an HTTP interface which looks for user roles.

There is one special case: If the database is empty, then the first user gets automatically created with an admin role. This check is by design not thread-safe. Therefore I created a static object which serves as lock. See the code below:

public class UserManagement : Controller
{
	private readonly QlcContext _dbContext;
	private readonly ILogger<UserManagement> _logger;
	private static Object userRoleCheckLock = new Object(); 

	public UserManagement(QlcContext dbContext, ILogger<UserManagement> logger)
	{
		_dbContext = dbContext;
		_logger = logger;
	}

	[HttpGet]
	[Route("GetRole")]
	public IActionResult GetRole(string user)
	{
		if (String.IsNullOrEmpty(user))
		{
			_logger.LogError("Missing user parameter");
			return BadRequest("Missing user parameter");
		}

		QlcUser foundUser;

		lock (userRoleCheckLock)
		{
			foundUser = _dbContext.QlcUser.SingleOrDefault(u => string.Equals(u.Name, user, StringComparison.InvariantCultureIgnoreCase));

			if (foundUser == null)
			{
				// If the user table is empty, then the first user which logs in, is admin else it is an normal user
				bool isAdmin = _dbContext.QlcUser.Count() == 0;
				Role role = isAdmin ? Role.Admin : Role.User;
				foundUser = new QlcUser { Name = user, Role = role };

				Log(Severity.TRACE,
					$"Database user table is empty. Creating first user '{user}' with the role '{foundUser.RoleDisplayName}'",
					user);

				_dbContext.QlcUser.Add(foundUser);
				_dbContext.SaveChanges();
			}
		}

		return Ok(foundUser.Role);
	}
	
	private void Log(Severity severity, string message, string requestor)
	{
		AuditTrail auditTrail = new AuditTrail(
			severity,
			DateTime.UtcNow,
			requestor,
			message);

		_dbContext.AuditTrail.Add(auditTrail);
		_dbContext.SaveChanges();
	}
}

The problem is, that I get regularly crashes with this code. The complete ASP.Net app crashes without any exceptions and without any log! How is this possible? Shouldn't this work?!

Thx in advance for answers!

Best regards,
Stefano


Viewing all articles
Browse latest Browse all 9386

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>