0
votes

I am developing a CRM by .net core mvc and EF which needs a lot of DB connection to retrieve and update information. From time to time I face this error during debugging, this is a big project with a lot of users I don't know how it will work in real usage!

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.\r\nObject name: 'XXX'.

before I used this setting in startup.cs:

services.AddDbContext<XXX>
                (option => 
                option.UseSqlServer(Configuration.GetConnectionString("YYY"))
                .ServiceLifetime.Singleton);

that setting was lead to another error occasionally:

System.InvalidOperationException: The instance of entity type 'TblZZZ' cannot be tracked because another instance with the same key value for {'ZZZId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

so I have changed my setting to:

services.AddDbContext<XXX>
                (option => 
                option.UseSqlServer(Configuration.GetConnectionString("YYY"))
                .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));

now I am facing the Cannot access a disposed context instance. I don't know what setting can solve my issue.

I m using net5.0

Update: my partial class:

public partial class TblXXX
    {
        private ZZZ context;//context
        public TblXXX(ZZZ _context)
        {
            context = _context;
        }
        public TblXXX() { }
//function for check username
   public bool CheckUsernameExit(string username) {
            var u = context.TblXXX
                .Where(e => e.Username == username)
                .FirstOrDefault();
            return (u != null);
        }
}

in my controller:

  public IActionResult Check(UserModelView user)
        {
            if (ModelState.IsValid)
            {
                var r = _viewModel.tblXXX.CheckUsernameExit(user.tblXXX.Username);
                if (r)
                {
                    toastNotification.AddErrorToastMessage("This email is in use. Enter differernt email.");
                 
                    return View("Create", _viewModel);
                }
            

and this is my ViewModel:

 public class UserModelView
    {
        public TblXXX tblXXX { get; set; }
        public List<TblXXX > tblXXXList { get; set; }
    }
          

this is one of the cases I face the error.

1
Use AddDbContext<XXX> and configure just the connection string is enough, don't try to modify the service lifetime which is Scoped by default (and should always be so). You must have a problem somewhere else, I'm pretty sure about that. So now you don't even know where it could be, we may be all stuck with this. - King King
Don't use Singleton lifetime, use Scoped or even Transient depending on how you are using it in code - Crowcoder
@KingKing it is a very big project but if I want to summarize it when I face this issue become this: I made some partial classes alongside EF generated partial classes. in my classes, I try to do different functions such as some complicated queries and simple ones like an update directly by linq or even SPs. in the controller, if I don't make new objects of my partial class with dbcontext in constructor I faced this error. it seems they need fresh dbcontext always! - Paria Shiri
thank you for the reply @KingKing - Paria Shiri

1 Answers

0
votes

In asp.net core the DbContext should be a Scoped service, not a Singleton.

Change this:

services.AddDbContext<XXX>
                (option => 
                option.UseSqlServer(Configuration.GetConnectionString("YYY"))
                .ServiceLifetime.Singleton);

To

services.AddDbContext<XXX>
                (option => 
                option.UseSqlServer(Configuration.GetConnectionString("YYY")));