I have a problem managing the lifetime of open database connections with StructureMap scoped to HttpContext when there are persistent HTTP connections in my ASP.NET MVC application, like SignalR hubs.
My DI container, StructureMap, injects an open IDbConnection into several services. To ensure that these database connections are closed and properly disposed of, I call ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects() on the EndRequest event.
This works great for MVC controllers until a service requiring a database connection is injected into a SignalR hub, which keeps a persistent HTTP connection open for each client and eventually saturates the connection pool.
If I scope IDbConnection to a singleton, only one connection is ever opened per-application and the pool doesn't saturate, but this is a bad idea in case the connection is ever locked or times out.
So maybe there is a way to customise the scope of database connections for my SignalR hubs? I tried resolving a service instance in each Hub method, but this still instantiates a database connection at the HttpContext scope and keeps it open for the duration of the calling client's hub connection.
How should I manage the lifetime of database connections with StructureMap in an HTTP-scoped context when there are persistent HTTP connections around?
Example Code
Typical Service
public class MyService
{
private IDbConnection _con;
public MyService(IDbConnection con)
{
_con = con;
}
public IEnumerable<string> GetStuff()
{
return _con.Select<string>("SELECT someString FROM SomeTable").ToList();
}
}
Typical SignalR Hub
public class MyHub : Hub
{
private MyService _service;
public MyHub(MyService service)
{
_service = service; // Oh Noes! This will open a database connection
// for each Client because of HttpContext scope
}
public Task AddMessage()
{
var result = _service.GetStuff();
// ...
}
}
StructureMap Configuration
For<IDbConnection>()
.HybridHttpOrThreadLocalScoped()
.Use(() => BaseController.GetOpenConnection(MyConnectionString));
Global.asax.cs
public class GlobalApplication : System.Web.HttpApplication
{
public GlobalApplication()
{
EndRequest += delegate
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
};
}
// ...
}
In SignalR 1.0.0 Alpha, Hub's implement IDisposable. SignalR Hub instances are ephemeral unlike the HttpContext, so if you close your your IDbConnection in the Hub's Dispose method, you shouldn't unnecessarily saturate your connection pool.
Solution using transient database connection and nested StructureMap container
First, configure a named, transient database connection instance in StructureMap:
For<IDbConnection>()
.Transient() // scope
.Add(x => BaseController.GetOpenConnection(connectionString, IsDebugging()))
.Named("Transient");
Make sure you configure this before your default instance, or it will override the default instance.
Secondly, inject an IContainer into your SignalR hub so you can build a nested StructureMap container:
public class JobHub : Hub
{
private readonly IContainer _container;
public JobHub(IContainer container)
{
_container = container;
}
public Task DoStuff(string input)
{
// ...
Instantiate a nested container in your SignalR method and resolve your named transient database connection:
using (var httpRequestScope = _container.GetNestedContainer())
{
var transientConnection =
httpRequestScope.GetInstance<IDbConnection>("Transient");
Use .With<IDbConnection>(transientConnection) to ensure services and repositories instantiated by your nested container use this connection:
var myService = httpRequestScope
.With<IDbConnection>(transientConnection)
.GetInstance<MyService>();
var result = myService.DoStuff(input);
return Clients.addResult(result);
}
}
}
Finally, the scoped using (...) statement will ensure that your nested container cleans up after itself, including the database connection.
The downside here is that you are opening and closing a database connection for every SignalR method call, but since connections are pooled, releasing early may not be so bad. Your mileage should depend on your SignalR request volume.
You may be able to ditch the nested container and just ask DependencyResolver.Current for the named connection instance, but then you may have to remember to explicitly close each connection to prevent a leak.
Related
I would like to request all created instances from a transient service via the IServiceProvdier. My problem is that requesting them seems to create additional instances instead of retrieving only the already existing instances.
I have a service interface and implementation
public interface ISomeService {}
public class SomeService : ISomeService
{
public SomeService()
{
}
}
It is registered transient
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISomeService, SomeService>();
}
Another service where I try to get all already created services
public class AnotherService
{
// calls the constructor of SomeService
//public AnotherService(IEnumerable<ISomeService> instances) {}
public AnotherService(IServiceProvider serviceProvider)
{
// calls the constructor of SomeService
//IEnumerable<ISomeService> instances = serviceProvider.GetServices<ISomeService>();
// calls the constructor of SomeService
//IEnumerable<ISomeService> instances = serviceProvider.GetRequiredServices<ISomeService>();
}
}
I don't know why the constructor of SomeService is called but it definitly seems to do it due to the calls of Get...
Anyone managed to get the list of instances without creating one?
By definition a transient service will always be created each time you request the service provider or the DI system to resolve it.
If you want to reuse the same instances you can register services with a different lifetime
services.AddSingleton<ISomeService, SomeService>();
or
services.AddScoped<ISomeService, SomeService>();
if you register the dependency as a singleton than there will be a single instance of there service for the entire application lifetime.
if you register the dependency with the scoped lifetime than a new instance will be created for each scope. In Asp.Net a scope consists of a request.
If you want your dependency to be transient and want to have track of all the instances that have been created you can do a little trick using static references:
public static class SomeServiceReferences {
public static readonly IList<ISomeService> References { get; } = new List<ISomeService>();
}
public class SomeService: ISomeService {
public SomeService() {
SsomeServiceReferences.References.Add(this);
}
}
but I don't reccomend this approach cause holding the reference of those dependencies might cause performance problems and if you need to do such a thing there might be some problems with the design of your application.
Are objects that are referenced, not created, within a factory implementation disposed by the container? See code below:
services.AddTransient(c => OwinContext.ServiceObject);
Will ServiceObject, which implements IDisposable, be disposed by the container considering it isn't created (i.e. new ServiceObject)?
ServiceObject is currently registered as Scoped, but we are getting ObjectDisposedException on the rare occasion. I'm guessing it's getting disposed within OWIN sometimes before our services are able to use it, which is why I was hoping of making it Transient but I'm worried the container will dispose of it more frequently.
Disposable transient registrations are tracked by the container and disposed when their scope ends.
The Microsoft documentation is not always clear about this, as this documentation seems to suggest that "The framework does not dispose of the services automatically" that are "not created by the service container." Although the documentation is not incorrect, as it primarily talks about the registration of instances through the AddSingleton<T>(T instance) extension method — it is misleading because it doesn't hold for:
AddSingleton<T>(Func<IServiceProvider, T>),
AddScoped<T>(Func<IServiceProvider, T>), and
AddTransient<T>(Func<IServiceProvider, T>).
This statement can be easily verified using the following program:
using Microsoft.Extensions.DependencyInjection;
var disposable = new FakeDisposable();
var services = new ServiceCollection();
services.AddTransient(c => disposable);
var provider = services.BuildServiceProvider(validateScopes: true);
using (var scope = provider.CreateScope())
{
scope.ServiceProvider.GetRequiredService<FakeDisposable>();
}
public class FakeDisposable : IDisposable
{
public void Dispose() => Console.WriteLine("Disposed");
}
Output:
Disposed
Conclusion: Yes, transient registrations for disposable objects are disposed of by the container.
There will be little difference between making this registration Transient or Scoped. In both cases the object will get disposed when the scope ends.
In the case of a Transient registration, though, you'll start to see the disposable get disposed of multiple times in case it gets injected multiple times. For instance:
using (var scope = provider.CreateScope())
{
scope.ServiceProvider.GetRequiredService<FakeDisposable>();
scope.ServiceProvider.GetRequiredService<FakeDisposable>();
scope.ServiceProvider.GetRequiredService<FakeDisposable>();
}
Output:
Disposed
Disposed
Disposed
From reliability, however, it's better to stick with a Scoped registration, instead of Transient. This is because MS.DI will prevent Scoped registrations from being injected into Singleton consumers (in case the Service Provider is created by calling BuildServiceProvider(validateScopes: true)). In case your ServiceContext would get injected into a Singleton, it causes it to become a Captive Dependency and keep referenced (and likely used) by that Singleton, long after it got disposed of.
The most likely reason you are getting those ObjectDisposedExceptions is because Owin tries to use the ServiceContext after your (web request) scope is disposed.
The ServiceContext object is likely being controlled and disposed of by OWIN, which doesn't make it a good candidate to be disposed of by the container. But here's the problem: MS.DI will always try to dispose of Transient and Scoped registrations and the only way to prevent this from happening is to not register your ServiceContext.
The solution, therefore, is to wrap it in a "provider" object of some sort. For instance:
// New abstraction
public interface IServiceObjectProvider
{
object ServiceObject { get; }
}
// Implementation part of your Composition Root (see: https://mng.bz/K1qZ)
public class AmbientOwinServiceObjectProvider : IServiceObjectProvider
{
public object ServiceObject => OwinContext.ServiceObject;
}
// Registration:
services.AddScoped<IServiceObjectProvider, AmbientOwinServiceObjectProvider>();
// Usage:
public class MyController : Controller
{
private readonly IServiceObjectProvider provider;
public MyController(IServiceObjectProvider provider)
{
// Only store the dependency here: don't use it,
// see: https://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple/
this.provider = provider;
}
public string Index()
{
var so = this.provider.ServiceObject;
// Do something with the Service object
}
}
I use Unity in an MVC5 project (.net461) for DI and I want to register a service with multiple lifetimes.
With the classic core DI I would use RegisterScoped and that's it. Whenever the service is resolved within an Http Request I would reuse the same instance for the duration of the request. If I want to fire a background task, that background task should open a service scope, and I would resolve a new instance for the service for the duration of that scope. No need to have different registrations for the service. In the first case, the scope is created by the runtime, and in the second it is manually created by the developer. In both cases, the service provider only knows that the service is scoped, it doesn't care about where and how the scope has opened.
With Unity the first case is solved with PerRequestLifetimeManager. The second case is solved with a HierarchicalLifetimeManager.
But how should I have a combination of the two?
Whenever a service is resolved within an HttpRequest (in a controller constructor for instace) it should use the PerRequestLifetimeManager and wherever it is resolved in a child container (within the constructor of another service that is instantiated in the child container) it should use HierarchicalLifetimeManager.
How can I register the service with both managers?
At the end of the day, I had to implement my own solution which is based on (but not using) Unity.Mvc, Unity.WebApi packages, and the HierarchicalLifetimeManager.
None of the solutions I found online worked for my case. Most of them covered only the per request part, but not the per custom user scope part.
The key of the solution is not the lifetime manager but the dependency resolver. The lifetime manager for my requirements should always be HierarchicalLifetimeManager because that is what I truly need. A new container for each scope, which is covered by child containers and HierarchicalLifetimeManager.
Using Integrating ASP.NET Core Dependency Injection in MVC 4 as an example on how to implement your own dependency resolver, I came up with the solution below.
What I had to do, is to make sure a new scope is created on the beginning of the Http Request, and Disposed at the end of the Http Request. This part is covered by implementing a simple HttpModule. This part is similar to the HttpModule used by the official Unity Per Request Lifetime implementation.
Per Http Request Module
This is the module implementation
internal class UnityPerHttpRequestModule : IHttpModule
{
private static IUnityContainer _rootContainer;
public void Init(HttpApplication context)
{
context.BeginRequest += (s, e) =>
((HttpApplication)s).Context.Items[typeof(UnityPerHttpRequestModule)]
= _rootContainer.CreateChildContainer();
context.EndRequest += (s, e) =>
(((HttpApplication)s).Context.Items[typeof(UnityPerHttpRequestModule)]
as IUnityContainer)?.Dispose();
}
public static void SetRootContainer(IUnityContainer rootContainer)
{
_rootContainer = rootContainer ?? throw new ArgumentNullException(nameof(rootContainer));
}
public void Dispose() { }
}
On Beginning the request we create a new child container and place it in the HttpRequest Items dictionary.
On Ending the request we retrieve the child container from the Items dictionary and dispose it.
The static method SetRootContainer should be called once at the startup of the application to pass in the initial root Unity container, the one that services are registered on.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
UnityPerHttpRequestModule.SetRootContainer(UnityConfig.Container); // pass here the root container instance
...
}
}
We also need to register the module with owin.
using Microsoft.Owin;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Owin;
[assembly: OwinStartup(typeof(MyApp.Startup))]
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyApp.Startup), nameof(MyApp.Startup.InitScopedServicesModule))]
namespace MyApp
{
public partial class Startup
{
public static void InitScopedServicesModule()
{
DynamicModuleUtility.RegisterModule(typeof(UnityPerHttpRequestModule));
}
public void Configuration(IAppBuilder app)
{
}
}
}
MVC Dependency Resolver
Now the http module is registered and we have a new scope created on each request. Now we need to instruct MVC and WebApi to use that scope. For this, we need to create the appropriate dependency resolvers. I created one dependency resolver for MVC and one for WebApi since they need to implement different interfaces (I could have implemented both in the same class though).
The dependency resolver for MVC is this:
internal class UnityMvcPerHttpRequestDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer rootContainer;
internal UnityMvcPerHttpRequestDependencyResolver(IUnityContainer rootContainer)
{
this.rootContainer = rootContainer;
}
internal IUnityContainer Current => (HttpContext.Current?.Items[typeof(UnityPerHttpRequestModule)] as IUnityContainer) ?? this.rootContainer;
public void Dispose() { }
public object GetService(Type serviceType)
{
try
{
return Current.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return Current.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
}
What the resolver does is that it checks for an HTTP Context and gets the unity container in the Context's item dictionary and uses this container to resolve the services. So effectively, if the service requested is registered with a Hierarchical Lifetime, a new instance of that service will be created within the child container (aka within the context of the request). Since the child container is disposed at the end of the request by the http module, any services instantiated in the child container are also disposed.
Things to notice here:
The IDependencyResolver interface here is the System.Web.Mvc.IDependencyResolver. This is the interface expected by the MVC. The WebApi expects a difference IDependencyResolver (same name, different namespaces)
Catching ResolutionFailedException. If you don't catch those exceptions, the application will crash.
Now that we have the MVC dependecy resolver, we need to instruct MVC to use this resolver.
public static class UnityMvcActivator
{
public static void Start()
{
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
//DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityMvcPerHttpRequestDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
//Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
}
Things to notice here:
Do not register the official UnityPerRequestHttpModule since we implement our own. ( I could probably use that module but my implementation would depend on the inner implementation of the official module and I don't want that, since it may change later)
Web Api Dependency Resolver
Simlilar to MVC dependency resolver, we need to implement one for the Web Api
internal class UnityWebApiPerHttpRequestDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer rootContainer;
internal UnityWebApiPerHttpRequestDependencyResolver(IUnityContainer rootContainer)
{
this.rootContainer = rootContainer;
}
internal IUnityContainer Current => (HttpContext.Current?.Items[typeof(UnityPerHttpRequestModule)] as IUnityContainer) ?? this.rootContainer;
public IDependencyScope BeginScope() => this;
// Dispose, GetService and GetServices are the same as MVC dependency resolver
}
Things to notice here:
IDependencyResolver here is of type System.Web.Http.Dependencies.IDependencyResolver. It is not the same as MVC's IDependencyResolver.
This Dependency resolver interface implements one more method: BeginScope. This is important here. WebApi pipeline is different that MVC pipeline. WebApi engine, by default, calls BeginScope to open a new scope for each web api request, and uses that scope to resolve controllers and services. So, Web api has already a scoped mechanism. BUT we have already created a scope ourselves with our per request module and we want to use that scope. So what we have to do here is to not create a new scope again. It already exists. So calling BeginScope on our resolver should return the same resolver scope, thus we return this.
Now that we have created the WebApi resolver, we have to also register it to web api.
using System.Web.Http;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyApp.UnityWebApiActivator), nameof(MyApp.UnityWebApiActivator.Start))]
namespace MyApp
{
/// <summary>
/// Provides the bootstrapping for integrating Unity with WebApi when it is hosted in ASP.NET.
/// </summary>
public static class UnityWebApiActivator
{
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start()
{
// Use UnityHierarchicalDependencyResolver if you want to use
// a new child container for each IHttpController resolution.
// var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.Container);
var resolver = new UnityWebApiPerHttpRequestDependencyResolver(UnityConfig.Container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
}
}
Registering services
Now that we have set up and registered all our Resolvers and modules, the last thing to do is to remember to register each scoped service with HierarchicalLifetimeManager. Since our scoped solution depends on child containers, registering our scoped services that way will suffice.
Conclusion
And with that, I managed to implement a working scoped DI solution with Unity. The example below did not work with the official Per Request Lifetime solution, but worked with my custom implementation.
class TestController{
private readonly IMyScopedService service;
private readonly IUnityContainer container;
public TestController(IUnityContainer container, IMyScopedService service){
this.service = service;
this.container = container;
}
public ActionResult Post( ... ){
var childContainer = this.container.CreateChildContainer();
var scopedService = childContainer.GetService<IMyScopedService>()
HostingEnviroment.QueueBackgroundWorkItem(() => {
using(childContainer){
scopedService.DoWork();
}
});
}
}
With the official PerRequestLifetimeManager solution, this.service and scopedService were the same instance. The scoped service was instantiated in the http context, then the same instance was fetched again from the child container (since it was registerd with PerRequestLifetimeManager and not HierarchicalLifetimeManager) and passed to the background Job. The background job outlives the http request. The instance is disposed when the Http requests ends, but it is still being used in the background job which probably runs in another thread. Concurrency issues (and more) arise. For instance you can't use the same instance of an EF DbContext in multiple threads.
With the custom implementation above, the example works. scopedService is a different instance since it is registered with a HierarchicalLifetimeManager. this.services is disposed when the http request ends but scopedService lives during the whole execution of the background Job.
What we effectively do is control the lifetime of the services by controlling the lifetime of child containers. And I have the impression that this is the solution for every scoped service scenario.
Register all scoped services with HierarchicalLifetimeManager
Control the lifetime of services by controlling the lifetime of the child containers.
I am very new with orleans and trying to grasp everything with grains and so forth.
What i got is that in my startup.cs file i add the SignalR like this
public IServiceProvider ConfigureServices(IServiceCollection services)
{
Program.WriteConsole("Adding singletons");
services
.AddSingleton(achievementManager)
.AddMvc();
services.AddSingleton(SignalRClient);
return services.BuildServiceProvider();
}
So far everything is fine i can start my host/application and it connects to SignalR as it should. But what i cant wrap my head around is how do i get this down to my grain? if i had a controller i would simply send it down in the constructor on startup but how do i do this with a grain? Or can i even do it like this. Any guidance is appreciated.
In the grain then i want to do something like this
[StatelessWorker]
[Reentrant]
public class NotifierGrain : Grain, INotifierGrain
{
private HubConnection SignalRClient { get; }
public NotifierGrain(HubConnection signalRClient)
{
SignalRClient = signalRClient;
SignalRClient.SendAsync(Methods.RegisterService, Constants.ServiceName);
}
public Task NotifyClients(object message, MessageType type)
{
var registerUserNotification = (RegisterUserNotificationModel)message;
SignalRClient.SendAsync(Methods.RegisterUserToMultipleGroups, registerUserNotification.UserId, registerUserNotification.InfoIds);
}
return Task.CompletedTask;
}
Then i try to call the Notify method from another grain like this
var notifier = GrainFactory.GetGrain<INotifierGrain>(Constants.NotifierGrain);
await notifier.NotifyClients(notification, MessageType.RegisterUser);
But trying to do this ends up with an error like this
InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.SignalR.Client.HubConnection' while attempting to activate 'User.Implementation.Grains.NotifierGrain'.
Orleans supports constructor injection, so you can inject the SignalRClient into your grain constructor. In your code you are already correctly registering the client using services.AddSingleton(SignalRClient), so I will focus on how to inject the type into your grain.
I do not know what the type the SignalR client object is, but in this example I assume that the type is "SignalRClient":
[StatelessWorker]
[Reentrant]
public class NotifierGrain : Grain, INotifierGrain
{
private readonly SignalRClient signalRClient;
public NotifierGrain(SignalRClient signalRClient)
{
this.signalRClient = signalRClient;
}
public async Task NotifyClients(object message, MessageType type)
{
var registerUserNotification = (RegisterUserNotificationModel)message;
await this.signalRClient.SendAsync(
MessageMethods.RegisterUserToMultipleGroups,
registerUserNotification.UserId,
registerUserNotification.infoIds);
}
}
Depends how you're thinking to use SignalR Server, if you're going to host your SignalR server with Microsoft Orleans for sure you need to have backplane to handle the Orleans cluster communications.
You can use SignalR Orleans which has everything done out of the box for you :)
Also if you need a reactive SignalR library for the frontend, you can use Sketch7 SignalR Client
PS I m one of the authors of both libraries.
I'm using Entity Framework 4 and I have created a UnitOfWork class that creates my Context and exposes that through a public property as a IContext interface.
The Context class inherits from ObjectContext and exposes my Poco entities as public properties e.g.
public IObjectSet<User> Users
{
get { return _users ?? (_users = CreateObjectSet<User>("Users")); }
}
private IObjectSet<User> _users;
I have also created a few repository classes that takes that context as a constructor parameter and uses that context when executing queries in the repository classes. This is how I use the whole thing together:
using(var uow = new UnitOfWork(connectionstring))
{
using(var repository = new UserRepository(uio.Context))
{
//This is the place where a connection is opened in the database
var user = repository.GetUserByName(username);
}
}
//The connection is still open here even though
The UnitOfWork class implementes the IDisposable interface and calls Context.Dispose() inside it's Dispose method.
When I close my application the open connection in my database is gone, so my question is: What is going on here? :-) How should I properly dispose the Context (ObjectContext) instance in my UnitOfWork class in order to close the opened connection in my database?
I think you are doing things properly with regard to disposing the Context. The Sql Server Provider supports connection pooling, so what you're seeing after the end of the using(var uow = new UnitOfWork(connectionstring)) block is the connection in the pool.
For more information on connection pooling, see this article: http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx