skip to Main Content

I have a Asp.Net web app that used for validation, a scanner is connected to it through serial port and whenever a qr code is scanned, It gets the data and the page is refreshed and uses the new data gotten from the qr code. My problem now is that whenever I scan, and data is received in my controller function, which is shown below.

public void mySerialPort_Data(object sender, SerialDataReceivedEventArgs e)
        {            
            try
            {
                string data = _serialPort.ReadExisting();
                barcode = data.Split(";");
                codeValue = barcode[0].Substring(barcode[0].IndexOf(":") +1);
                SelectedPN(pn_No);
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex);
            }
            
        }

I call the controller function of the current page in the function above SelectedPN() and this function I think is supposed to load and refresh the data I got from the qr code, but I keep getting an error.
Below is the SelectedPN() function that is called in the function above

 public ActionResult SelectedPN(String nameobj)
        {
            
            pn_No= nameobj;
            _serialPort.WriteTimeout = 500;

            _serialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_Data);

            if (!_serialPort.IsOpen)
            {
                try
                {
                    _serialPort.Open();

                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex);
                }
            }

            ViewBag.check9 = codeValue;
            List <double> newList = new List<double>();
            var num = 0;
            var bill = 4;

            
            var categoryFromDb = _db.Categories1.Where(j => j.MaterialNumber == nameobj);
            foreach (var obj in categoryFromDb) { 
                newList.Add(obj.ComponentNumber);
            }
            num = newList.Count;
            var duplicates = newList.GroupBy(x => x)
                            .SelectMany(g => g.Skip(1))
                            .Distinct()
                            .ToList();
           
            
            ViewBag.check1 = check;
            //testlist.Add(Convert.ToDouble(data1.X2));
            ViewBag.check1 = check;
            ViewBag.check2 = "background-color: #00FF00;";
            ViewBag.check3 = 3;
            ViewBag.check4 = num;
            //ViewBag.check5 = '';
            ViewBag.update = num;
            changeValue = num;
            ViewBag.check6 = testlist;
            ViewBag.check7 = duplicates;



            return View( categoryFromDb );
        }

The error is that it says the instance of my dbContext has been disposed and therefore i cannot use it.

System.ObjectDisposedException: 'Cannot access a disposed context instance. A common cause of this error is disposing a context instance 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' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'ApplicationDbContext'.'

What I have tried
I found online in a post that ServiceLiftime of DbContext is set to Scoped by default, and it disposes the instance once it is used and I have to change it to ServiceLifetime.Transient to be able to resuse the instance, but this did not work. I still got the same error again

Below is where I set the ServiceLiftime

builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(
    builder.Configuration.GetConnectionString("DefaultConnection")
    ), ServiceLifetime.Transient);

I would appreciate any help on how to solve this problem.

EDIT

This is my complete controller

namespace WA4.Controllers
{
    
    public class CategoryController : Controller
    {
        
        static SerialPort _serialPort = new SerialPort("COM3", 115200, Parity.None, 8, StopBits.One);
        
        public IEnumerable<Category> categoryFromDb;
        

        public CategoryController(ApplicationDbContext db)
        {
            _db = db;
        }

        public IActionResult Index()
        {
            getPorts();
            IEnumerable<Category> objCategoryList = _db.Categories1;
            return View(objCategoryList);
        }


        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult SelectedPN(String nameobj)
        {
            
            pn_No= nameobj;
            
            _serialPort.WriteTimeout = 500;

            _serialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_Data);

            if (!_serialPort.IsOpen)
            {
                try
                {
                    _serialPort.Open();

                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex);
                }
            }

            ViewBag.check9 = codeValue;
            List <double> newList = new List<double>();
            var num = 0;
            var bill = 4;




            
                categoryFromDb = _db.Categories1.Where(j => j.MaterialNumber == nameobj);
            

                foreach (var obj in categoryFromDb) {
                    newList.Add(obj.ComponentNumber);
                }
            num = newList.Count;
            var duplicates = newList.GroupBy(x => x)
                            .SelectMany(g => g.Skip(1))
                            .Distinct()
                            .ToList();
               
        
            return View( categoryFromDb );
            
        }

And below is my DbContext.cs content

using WA4.Models;
using Microsoft.EntityFrameworkCore;

namespace WA4.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext()
        {
        }

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {

        }

        public DbSet<Category> Categories1 { get; set; }
    }
}

I tried using the solution @Walsharoo suggested but I got an error instead

 using (ApplicationDbContext _db = new() )
            {
                categoryFromDb = _db.Categories1.Where(j => j.MaterialNumber == nameobj);
            

                foreach (var obj in categoryFromDb) {
                    newList.Add(obj.ComponentNumber);
                }
            num = newList.Count;
            var duplicates = newList.GroupBy(x => x)
                            .SelectMany(g => g.Skip(1))
                            .Distinct()
                            .ToList();

Error

InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the 'DbContext.OnConfiguring' method or by using 'AddDbContext' on the application service provider. If 'AddDbContext' is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, DbContextOptions contextOptions, DbContext context)
Microsoft.EntityFrameworkCore.DbContext.get_ContextServices()
Microsoft.EntityFrameworkCore.DbContext.get_Model()
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.get_EntityType()
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.get_EntityQueryable()
Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.System.Linq.IQueryable.get_Provider()
System.Linq.Queryable.Where<TSource>(IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
WA4.Controllers.CategoryController.SelectedPN(string nameobj)
lambda_method86(Closure , object , object[] )
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

EDIT

This is the stack trace after following the suggestion of @Roberto Ferraris

    Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()   Unknown
    Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.DbContext.ContextServices.get() Unknown
    Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.DbContext.ChangeTracker.get()   Unknown
    Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.Query.CompiledQueryCacheKeyGenerator.GenerateCacheKeyCore(System.Linq.Expressions.Expression query, bool async) Unknown
    Microsoft.EntityFrameworkCore.Relational.dll!Microsoft.EntityFrameworkCore.Query.RelationalCompiledQueryCacheKeyGenerator.GenerateCacheKeyCore(System.Linq.Expressions.Expression query, bool async)    Unknown
    Microsoft.EntityFrameworkCore.SqlServer.dll!Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerCompiledQueryCacheKeyGenerator.GenerateCacheKey(System.Linq.Expressions.Expression query, bool async)   Unknown
    Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute<System.Collections.Generic.IEnumerable<WA4.Models.Category>>(System.Linq.Expressions.Expression query) Unknown
    Microsoft.EntityFrameworkCore.dll!Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable<WA4.Models.Category>.GetEnumerator() Unknown
    System.Private.CoreLib.dll!System.Collections.Generic.List<WA4.Models.Category>.List(System.Collections.Generic.IEnumerable<WA4.Models.Category> collection)    Unknown
    System.Linq.dll!System.Linq.Enumerable.ToList<WA4.Models.Category>(System.Collections.Generic.IEnumerable<WA4.Models.Category> source)  Unknown
>   WA4.dll!WA4.Controllers.CategoryController.SelectedPN(string nameobj) Line 87   C#
    WA4.dll!WA4.Controllers.CategoryController.mySerialPort_Data(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) Line 315 C#
    System.IO.Ports.dll!System.IO.Ports.SerialPort.CatchReceivedEvents(object src, System.IO.Ports.SerialDataReceivedEventArgs e)   Unknown
    System.IO.Ports.dll!System.IO.Ports.SerialStream.EventLoopRunner.CallReceiveEvents(object state)    Unknown
    System.Private.CoreLib.dll!System.Threading.QueueUserWorkItemCallback..cctor.AnonymousMethod__6_0(System.Threading.QueueUserWorkItemCallback quwi)  Unknown
    System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunForThreadPoolUnsafe<System.__Canon>(System.Threading.ExecutionContext executionContext, System.Action<System.__Canon> callback, System.__Canon state)   Unknown
    System.Private.CoreLib.dll!System.Threading.QueueUserWorkItemCallback.Execute() Unknown
    System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()  Unknown
    System.Private.CoreLib.dll!System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart() Unknown
    System.Private.CoreLib.dll!System.Threading.Thread.StartCallback()  Unknown

2

Answers


  1. Somewhere in your code you have disposed your datacontext.

    Try using a new instance of it.

    ienumerable<object> categoryFromDb;
    
    using (DataClasses1DataContext _db = new DataClasses1DataContext())
    {
        categoryFromDb = _db.Categories1.Where(j => j.MaterialNumber == nameobj);
    }
    
    foreach (var obj in categoryFromDb)
        newList.Add(obj.ComponentNumber);
    
    num = newList.Count;
    var duplicates = newList.GroupBy(x => x).SelectMany(g => g.Skip(1)).Distinct().ToList();
    
    Login or Signup to reply.
  2. I think that the problem is that you return categoryFromDb :

    return View( categoryFromDb );
    

    The categoryFromDb in fact is not a collection of elements, but it is simply a query definition:

    categoryFromDb = _db.Categories1.Where(j => j.MaterialNumber == nameobj);
    

    Linq use a deferred execution (see Introduction to LINQ Queries (C#) | Microsoft Learn) so each time you use this variable a query is execute against the database.

    Since you return the query with View(categoryFromDb) it will be resolved when the ActionResult is executed (and not at the return statement) and tipically at this time de db context was already disposed.

    I suggest to change your code to include something like ToArray or ToList, so that the query is executed and the results are loaded in the variable:

    categoryFromDb = _db.Categories1.Where(j => j.MaterialNumber == nameobj).ToList();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search