I'm making an n-tier MVC application using .NET Core 2.1 and Entity Framework. There is also a hosted MQTT queue on which my application listens as a client. I also make use of Dependency Injection. This works perfectly, until a message is pushed to the queue and I want to save that message to the db. Once that happens I get following ObjectDisposedException error message:
Cannot access a disposed object. A common cause of this error is disposing a context 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, or wrapping the context 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: 'xxxDbContext'.
I can click continue, after which the application just continues to work. He only throws the exception on the first message received from the queue. Every other action with the controllers/managers/repositories works just fine. My code is as follows:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDefaultIdentity<User>()
.AddEntityFrameworkStores<xxxDbContext>();
services.AddDbContext<xxxDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")
));
// Some identity configuration omitted here
services.AddScoped<IIdeationRepository, IdeationRepository>();
services.AddScoped<IIdeationManager, IdeationManager>();
// Some other DI configuration omitted as well.
}
public Configure(IApplicationBuilder app, IHostingEnvironment env,
IApplicationLifetime applicationLifetime, IServiceProvider serviceProvider)
{
// Start MQTT
var broker = new MqttBroker(serviceProvider.GetService<IIdeationManager>(),
serviceProvider.GetService<IConfiguration>());
// On application exit terminate MQTT to make sure the connection is ended properly
applicationLifetime.ApplicationStopping.Register(() => broker.Terminate());
// Some default http pipeline code omitted
}
MqttBroker.cs
public MqttBroker(
[FromServices] IIdeationManager ideationManage,
[FromServices] IConfiguration configuration)
{
_ideationManager = ideationManager;
_configuration = configuration;
Initialize();
}
// Some code where I just parse the message and on receive send it to the
// ideation manager, this just works so I omitted it.
}
The manager just sends it directly to the repository, where the error message occurs.
Repository.cs
private xxxDbContext ctx;
public IdeationRepository(xxxDbContext xxxDbContext)
{
this.ctx = xxxDbContext;
}
// This method crashes with the error
public IdeationReply ReadIdeationReply(int id)
{
return ctx
.IdeationReplies
.Include(r => r.Votes)
.FirstOrDefault(r => r.IdeationReplyId == id);
}
DbContext.cs
public class xxxDbContext : IdentityDbContext<User>
{
public DbSet<Ideation> Ideations { get; set; }
// Some more dbsets omitted
public CityOfIdeasDbContext(DbContextOptions<CityOfIdeasDbContext> options)
: base (options)
{
CityOfIdeasDbInitializer.Initialize(this, dropCreateDatabase: false);
}
// In configuring I just create a logger, nothing special
// In OnModelCreating I just setup some value converters for other tables
// than the ones I need here
internal int CommitChanges()
{
if (delaySave)
{
int infectedRecords = base.SaveChanges();
return infectedRecords;
}
throw new InvalidOperationException(
"No UnitOfWork present, use SaveChanges instead");
}
}
I've read this but none of these situations seem to apply to me. And when I print the stacktrace in Dispose() it happens in the Main() method, so it doesn't really help me.
Anyone an idea how to solve or where I can search to solve this?
Thanks in advance!
IdeationRepositoryand how you use it, show us services/repo registrations inStartup.cstooIDisposableand disposing of the context, even though it's being injected. That's just a guess, because you haven't posted the full code for anything here. If that is the case, stop. You should only dispose of things owned by the class, i.e. it news them up explicitly. If it's injected, the class doesn't own it and therefore should not dispose of it.System.ObjectDisposedExceptionoccur, show us this method code