When running in developer mode, the ASP.NET Core configuration system (MS.DI) prevents the injection of Scoped dependencies (directly or indirectly) in Singleton consumers. It does this with its Scope-Validation feature. It does so because injecting Scoped dependencies typically have state and such Scoped dependency will be kept alive by the Singleton. This is a common pitfall named Captive Dependencies.
MS.DI, however, only performs this check in debug mode; probably because this check takes time. This means that after you deployed your application, MS.DI will not check for this kind of pitfall, because in that case the application is not running in development mode any longer.
But even though there's no exception, and you think "it works after publishing", you should prevent the injection of short-lived dependencies (such as Scoped dependencies) into long-lived dependencies (Singletons), because this can cause a myriad of hard to find bugs, especially with DbContext instances, because they are not thread-safe and their data get stale very soon.
This means that, whenever possible, lower the lifetime of the consumer (your listener) to either Scoped or Transient. In case the application only has one single instance of that listener, however, lowering the lifestyle has no effect; the instance will be inherently Singleton, no matter witch lifestyle to give it. In that case, the listener should become part of the Composition Root so it can manage IServiceScope
s directly. This way you can resolve DbContext
instances from a new IServiceScope every time the listener gets invoked.