locked
wo threads in use but also shows warnings about migrations when is none RRS feed

  • Question

  • User-183185495 posted

    Something has been worrying me about my design of how I access the dbconext for I have been getting a couple of clashes saying that the dbcontext is in use by another thread. Also the message claims there is migrations to be run but their is def not the migrations are up to date. I am using asp.net 3.1 and Entity framework core 3.1.5

    In My startup.cs I use the following to setup the context

    services.AddDbContext<MISDBContext>
    (options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);

    In my controller I inject it in the following way

    private readonly MISDBContext _context;
    
    
    public MISObjectsController(MISDBContext context, IStringLocalizer<MISObjectsController> localizer,
                   IStringLocalizer<SharedResource> sharedLocalizer, UserManager<ApplicationUser> userManager, IToastNotification toast) {
            _context = context;
            _sharedLocalizer = sharedLocalizer;
            _userManager = userManager;
            var list = _userManager.Users.Select(x => new SelectListItem() { Text = x.FirstName.ToUpperInvariant() + " " + x.LastName.ToUpperInvariant(), Value = x.Id.ToString() }).ToListAsync();
            ViewBag.Users = list;
            _toast = toast;   
    }

    Then in some function I would use it as such but I also do this inside of view components and am wondering is that how things are clashing saying that there is two threads in process.

    Something has been worrying me about my design of how I access the dbconext for I have been getting a couple of clashes saying that the dbcontext is in use by another thread. Also the message claims there is migrations to be run but their is def not the migrations are up to date. I am using asp.net 3.1 and Entity framework core 3.1.5
    
    In My startup.cs I use the following to setup the context
    
    services.AddDbContext<MISDBContext>
    (options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);
    In my controller I inject it in the following way
    
    private readonly MISDBContext _context;
    
    
    public MISObjectsController(MISDBContext context, IStringLocalizer<MISObjectsController> localizer,
                   IStringLocalizer<SharedResource> sharedLocalizer, UserManager<ApplicationUser> userManager, IToastNotification toast) {
            _context = context;
            _sharedLocalizer = sharedLocalizer;
            _userManager = userManager;
            var list = _userManager.Users.Select(x => new SelectListItem() { Text = x.FirstName.ToUpperInvariant() + " " + x.LastName.ToUpperInvariant(), Value = x.Id.ToString() }).ToListAsync();
            ViewBag.Users = list;
            _toast = toast;   
    }
    Then in some function I would use it as such but I also do this inside of view components and am wondering is that how things are clashing saying that there is two threads in process.
    
    [HttpPost]
    public async Task<IActionResult> AddToAuditTrail(string updateInfo) {
            var userId = GetCurrentTennantId().Result;
            var caseOfficer = _context.Users.Where(w => w.Id == userId.ToString()).FirstOrDefault();
            Int32.TryParse(TempData.Peek("CaseId").ToString(), out int resultCaseId);
            MISAuditTrail _auditrail = new MISAuditTrail();
            _auditrail.MISObjectId = resultCaseId;
            _auditrail.TennantId = userId;
            _auditrail.CreatedBy = caseOfficer.FirstName + caseOfficer.LastName.Substring(0, 1);
            _auditrail.Action = updateInfo;
            _auditrail.AuditType = (int)MISAuditTrail.AudItTypes.NOTES;
            _auditrail.CreatedDate = DateTime.Now;
            _auditrail.isActive = true;
            _auditrail.isDeleted = false;
    
            _context.Add(_auditrail);
            await _context.SaveChangesAsync();
            _toast.AddSuccessToastMessage("You have added an update to the case");
    
            return RedirectToAction("Edit", new { id = resultCaseId });
        }

    Thursday, August 6, 2020 8:26 AM

All replies

  • User475983607 posted

    The DdContext scope is configured as transient which creates a new instance each time the DbContext is injected.  Use Scoped which is the default.

    Thursday, August 6, 2020 11:02 AM
  • User-183185495 posted

    So remove this from the connection string?   

     ServiceLifetime.Transient

    The DdContext scope is configured as transient which creates a new instance each time the DbContext is injected.  Use Scoped which is the default.

    Thursday, August 6, 2020 8:15 PM
  • User-183185495 posted

    When I remove that I then get this which is why i set it to that mode following the article.

    A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913

    It Crashes at this code 

            public void GetUsersList() {
    
                List<SelectListItem> list = new List<SelectListItem>();
                var items = _context.Users.Where(w => w.Id != GetCurrentTennantId().ToString()).Select(sm => new {
                    Name = sm.FirstName + " " + sm.LastName,
                    Id = sm.Id.ToString()
                }).ToList();
    
                ViewBag.UserList = items;
            }

    mgebhard

    The DdContext scope is configured as transient which creates a new instance each time the DbContext is injected.  Use Scoped which is the default.

    Thursday, August 6, 2020 8:21 PM
  • User475983607 posted

    roguenidb

    When I remove that I then get this which is why i set it to that mode following the article.

    Transient is not a good option for a DbContext because the context is created each time it is injected.  That can cause a lot of overhead.

    Your design either creates more than one instance of the DbContext in a single request, you could be missing an await somewhere, or the design is leaking the DbContext between requests.  I assume GetCurrentTennantId() is the problem given the snippet of code but the problem could be elsewhere.

    Thursday, August 6, 2020 8:35 PM