Error: This is usually caused by different threads concurrently using the same instance of DbContext

Posted 3 years ago by hydeinthesky029
0

Good Day Everyone

IDE: Visual Studio 2019

Version 16.9

Project: Blazor Server Application

ORM: Entity Framwork Core

SQL Server: MS SQL Server 2016

 

I'm currently learning and practicing Blazor Server Application and Entity Framework, but I'm having a error below

"System.InvalidOperationException: 'A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently 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.'"

I have created mutliple services for my application, see the codes below.

Start Up:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MyBlazorAppPractice.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyBlazorAppPractice
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
            {
                services.AddRazorPages();
            services.AddServerSideBlazor();



            services.AddScoped<EmployeeServices>();
            services.AddScoped<StoredProcServices>();
            services.AddScoped<StatusServices>();
            services.AddScoped<ActiveService>();

            services.AddDbContext<AppDBContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("TestDBConnection")));



        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }
}

 

My services

Employee Services

using MyBlazorAppPractice.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyBlazorAppPractice.Data
{
    public class EmployeeServices
    {
        private readonly AppDBContext _dbContext;

        public EmployeeServices(AppDBContext dbContext)
        {
            _dbContext = dbContext;
        }

        public List<Employees> GetEmployees()
        {
            var emplist = _dbContext.Employees.ToList();
            return emplist;
        }

        public string AddEmployee(Employees employees)
        {
            try
            {
                _dbContext.Employees.Add(employees);
                _dbContext.SaveChanges();
                return "Save Success";
            }
            catch (Exception ex)
            {
                string GetError = ex.Message;
                return "ERROR";
            }

        }

        public Employees GetEmployeeByID(string id)
        {
            Employees employees = _dbContext.Employees.FirstOrDefault(s => s.EmployeeCode == id);
            return employees;
        }

        public string UpdateEmployee(Employees employees)
        {
            try
            {
                _dbContext.Employees.Update(employees);
                _dbContext.SaveChanges();
                return "Save Success";
            }
            catch (Exception ex)
            {
                string GetError = ex.Message;
                return "ERROR";
            }

        }

        public string DeleteEmployee(string EmployeeCode)
        {
            try
            {
                Employees employees = _dbContext.Employees.Find(EmployeeCode);
                if (employees != null)
                {
                    _dbContext.Employees.Remove(employees);
                    _dbContext.SaveChanges();

                }
                return "SUCCESS";
            }
            catch (Exception ex)
            {
                string GetError = ex.Message;
                return "ERROR";
            }

        }

    }
}

 

StatusServices:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyBlazorAppPractice.Data
{
    
    public class StatusServices
    {
        private readonly AppDBContext _dbContext;

        public StatusServices(AppDBContext dbContext)
        {
            _dbContext = dbContext;
        }

        public List<Status> GetStatuses()
        {
            var statuslist = _dbContext.Status.ToList();
            return statuslist;
        }

        public string AddStatus(Status status)
        {
            try
            {
                _dbContext.Status.Add(status);
                _dbContext.SaveChanges();
                return "SAVE SUCCESS";
            }
            catch(Exception ex)
            {
                string GetError = ex.Message;
                return "ERROR";
            }
        }

    }
}

 

StoredProcServices:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyBlazorAppPractice.Data
{
    public class StoredProcServices
    {

        private readonly AppDBContext _dbContext;

        public StoredProcServices(AppDBContext dBContext)
        {
            _dbContext = dBContext;
        }

        public string GetNewEmpCode()
        {
            string GNewEmpCode = "";
            
            try
            {
                List<sp_GenEmpCode> GList;
                string SqlStr = "exec sp_GenEmpCode";
                GList = _dbContext.sp_GenEmpCodes.FromSqlRaw<sp_GenEmpCode>(SqlStr).ToList();
                GNewEmpCode = GList[0].NewEmpCode.ToString();
                return GNewEmpCode;
            }
            catch(Exception ex)
            {
                string ExMsg = ex.Message;
                return GNewEmpCode = null;
            }
            
        }

    }
}

 

ActiveService

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyBlazorAppPractice.Data
{
    public class ActiveService
    {
        private List<GActive> _Active;

        public List<GActive> GetIsActive()
        {
            _Active = new List<GActive>() { new GActive() { Active = "True" },
                                           new GActive() { Active = "False"} };

            return _Active;
        }
    }
}

My DbContext

using Microsoft.EntityFrameworkCore;
using MyBlazorAppPractice.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyBlazorAppPractice.Data
{
    public class AppDBContext:DbContext
    {
        public AppDBContext(DbContextOptions<AppDBContext> options)
            : base(options)
        {

        }

        public DbSet<Employees> Employees { get; set; } 
        public DbSet<Items> Items { get; set; }

        public DbSet<Status> Status { get; set; }

        public DbSet<sp_GenEmpCode> sp_GenEmpCodes { get; set; }
    }
}

Code Behind

public class CreateEmployeeBase: ComponentBase
    {
        [Inject] EmployeeServices objEmpService { get; set; }
        [Inject] StoredProcServices objSPService { get; set; }
        [Inject] StatusServices objStatService { get; set; }

        [Inject] ActiveService objActiveService { get; set; }
        [Inject] NavigationManager NavMan { get; set; }

        public Employees objEmp = new Employees();
        public List<Status> objStat = new List<Status>();
        public List<GActive> objActive = new List<GActive>();
        public string StatusName { get; set; }
        public string Active { get; set; }

        protected override async Task OnInitializedAsync()
        {
            objActive = await Task.Run(() => objActiveService.GetIsActive());
            objStat = await Task.Run(() => objStatService.GetStatuses());
            await base.OnInitializedAsync();
        }

        protected void SaveEmployee()
        {
            
            objEmp.EmployeeCode = objSPService.GetNewEmpCode();
            objEmp.Status = StatusName;
            objEmp.Active = bool.Parse(Active);
            string GetResult = objEmpService.AddEmployee(objEmp);


            if(GetResult == "ERROR")
            {
                
            }
            else
            {
                NavMan.NavigateTo("EmployeeInfo/" + objEmp.EmployeeCode);
            }

        }


    }
    
    

Did I do something wrong? if Entity Framework does not work smooth on my projects I might probably jump back to ADO.NET, hope someone can help me on this.

Someone is typing...

Post a Reply

You must be logged in to add a new post.
Number of online users: 0
An error has occurred. This application may no longer respond until reloaded. Reload 🗙