We are in the middle of attempting a drop-in replacement of Autofac for Ninject in our windows service (before potentially making more enhancement to take care of Autofac features), but are running into a memory issue.
Here's a contrived example that doesn't reproduce our issue, but demonstrates the current layout of the app:
class Program
{
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
var ms = new MemoryStream(new byte[10000000]);
var ms2 = new MemoryStream(new byte[10000000]);
builder.RegisterType<BaseRepo>()
.WithParameter("ms", ms)
.As<IBaseRepo>();
builder.RegisterType<DerivedRepo>()
.WithParameter("ms", ms2)
.As<IDerivedRepo>();
builder.RegisterType<BaseFactory>().As<IBaseFactory>();
builder.RegisterType<Derived>().AsSelf();
builder.RegisterType<Derived>().Keyed<Base>(BaseEnum.Derived).As<Base>();
var container = builder.Build();
var factory = container.Resolve<IBaseFactory>();
while (true)
{
var instance = factory.Create(BaseEnum.Derived);
instance.DoSomething();
instance.Dispose();
Thread.Sleep(5000);
}
}
}
public interface IDerivedRepo : IDisposable {}
public class DerivedRepo : IDerivedRepo
{
private readonly MemoryStream _ms;
public DerivedRepo(MemoryStream ms)
{
_ms = ms;
}
public void Dispose()
{
_ms.Dispose();
}
}
public interface IBaseRepo : IDisposable {}
public class BaseRepo : IBaseRepo
{
private readonly MemoryStream _ms;
public BaseRepo(MemoryStream ms)
{
_ms = ms;
}
public void Dispose()
{
_ms.Dispose();
}
}
public enum BaseEnum
{
Derived = 1
}
public interface IBaseFactory
{
Base Create(BaseEnum baseEnum);
}
public class BaseFactory : IBaseFactory
{
private readonly IComponentContext _componentContext;
public BaseFactory(IComponentContext componentContext)
{
_componentContext = componentContext;
}
public Base Create(BaseEnum baseEnum)
{
return _componentContext.ResolveOptionalKeyed<Base>(baseEnum);
}
}
public interface IDisposableThing : IDisposable
{
void DoSomething();
}
public abstract class Base : IDisposableThing
{
protected readonly IBaseRepo BaseRepo;
protected Base(IBaseRepo baseRepo)
{
BaseRepo = baseRepo;
}
public void Dispose()
{
Console.WriteLine("Disposing base");
BaseRepo.Dispose();
}
public abstract void DisposeChildren();
public void DoSomething()
{
Console.WriteLine("Doing something");
}
}
public class Derived : Base
{
private readonly IDerivedRepo _derivedRepo;
public Derived(IBaseRepo baseRepo, IDerivedRepo derivedRepo) : base(baseRepo)
{
_derivedRepo = derivedRepo;
}
public override void DisposeChildren()
{
Console.WriteLine("Disposing derived");
_derivedRepo.Dispose();
}
}
Basically, we--at regular intervals--use a factory to instantiate an instance of an abstract class based on an enum value, do some work with that instance, then dispose of it. The problem is that those instances are not getting cleaned up by the garbage collector and the memory usage of the app increases steadily, with DebugDiag2 reporting that it is holding onto instances of the equivalent of our MemoryStream members in our repos (in our real app, these are wrappers over Entity Framework DBContext), with no other references to our code reported in its analysis so I have nothing else to go on.
I know there probably isn't enough here to give a definitive answer, what I'm more looking for is suggestions on where we are obviously doing something wrong (the whole team is new to Autofac and I know we are using the service locator anti-pattern, but I assume that isn't causing the problems we are seeing).
The behavior you experience is normal as Autofac keeps track, within a lifetime scope, of objects it resolves. These will be disposed when the associated lifetime scope is itself disposed. In your case, you only have one lifetime scope, the one created when you build the container from the builder.
I suggest that you have a good read of this documentation page which explains more in detail how lifetime scopes work.
A starting point would be to create an inner lifetime scope every time you start new work within the regular interval. It could look something like this:
var container = builder.Build();
while (true)
{
// Create an inner lifetime scope that will keep track of every
// object it creates
using (var lifetimeScope = container.BeginLifetimeScope())
{
// resolve objects from `lifetimeScope`
// do work with them
}
// At the end of the using directive, lifetimeScope will be disposed
// and will dispose with it any objects it kept track of
Thread.Sleep(5000);
}
Related
I have the following method in the aspx file (.NET Framework 4.6.2 project):
public static string SetAvgPeriodDays(int userId)
{
var service = new AveragePeriodDaysService(EfHelper.GetContext());
try
{
return service.SetAveragePeriodDays(userId);
}
catch (Exception e)
{
return e.Message;
}
}
AveragePeriodDaysService class has a constructor that accepts DbContext instance:
public class AveragePeriodDaysService
{
private readonly MyDbContext _ctx;
public AveragePeriodDaysService(MyDbContext ctx)
{
_ctx = ctx;
}
public string SetAveragePeriodDays(int userId)
{
// main logic goes here...
}
}
And here EfHelper class:
public class EfHelper
{
public static MyDbContext GetContext()
{
var options = new DbContextOptionsBuilder<MyDbContext>();
var connectionString = ...
options.UseSqlServer(connectionString);
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
return new MyDbContext(options.Options);
}
}
Question. Should I dispose MyDbContext? If yes, how should I do it properly?
As a rule you should never dispose dependencies that you got from outside because you never know who else uses same instance of this dependency. It means AveragePeriodDaysService can't dispose MyDbContext. But SetAvgPeriodDays knows exactly who will consume MyDbContext because it requested the creation of MyDbContext, hence it can and should dispose it after usage. Use using keyword:
public static string SetAvgPeriodDays(int userId)
{
using(var ctx = EfHelper.GetContext())
{
var service = new AveragePeriodDaysService(ctx);
try
{
return service.SetAveragePeriodDays(userId);
}
catch (Exception e)
{
return e.Message;
}
}
}
I'm actually not so sure what the correct patterns for this are, but I normally go with the following approach (something like the .NET Stream or SafeHandle classes do):
Your AveragePeriodDaysService really seems to take control of the context (it stores it in a private readonly field). So actually this class should implement IDisposable and dispose of the context itself.
On the other hand, you might want to use a single context for different "service" classes without always creating a new one. So it would be annoying if these classes always dispose the context.
So my way of implementing it would be something like this:
public class AveragePeriodDaysService : IDisposable
{
private readonly MyDbContext _ctx;
private readonly bool _ownContext;
public AveragePeriodDaysService(MyDbContext ctx, bool ownContext)
{
_ctx = ctx;
_ownContext = ownContext;
}
protected virtual void Dispose(bool disposing)
{
if (disposing) GC.SuppressFinalize(this);
if (_ownContext) _ctx.Dispose();
}
public void Dispose()
{
Dispose(true);
}
Then you can decide if the created instance should be responsible for disposing the context or if the creator needs to keep control.
Of course, if the created instance should take control, you need to properly dispose of this instance.
We are building an application where we have to have both old and new version to work side by side (V1 is old and V2 is new). Now to handle new flow we are using same old interfaces with everything being the same and differs only in functionality, hence now we have to define a named instance in-order to resolve the instances for new flow.
In the process teams have started using Service Factory Pattern as shown below
class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IServiceFactory serviceFactory)
{
_dataManager = serviceFactory.GetInstance<IDataManager>();
}
public void Execute()
{
_dataManager.Run();
}
}
Service Factory Class
public class ServiceFactory : IServiceFactory
{
private readonly IFeatureEvaluator _featureEvaluator;
public ServiceFactory(IFeatureEvaluator featureEvaluator)
{
_featureEvaluator = featureEvaluator;
}
public T GetInstance<T>()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
return ObjectFactory.GetInstance<T>("V2")
}
return ObjectFactory.GetInstance<T>();
}
}
Since Service Factory is anti-pattern and also it creates lot of complexities in retiring the old flow in future, I would want a way to initialize the dependencies at the container(structuremap ioc) itself or to work in a "Pure DI" way so that we can avoid headache. Any idea on how to tackle this.
Update:
IDataManager Implementation
public interface IDataManager
{
void Run();
}
public class OldFlow : IDataManager
{
public void Run()
{
//
}
}
public class NewFlow : IDataManager
{
public void Run()
{
//
}
}
IDataManager has 2 implementations and resolving the instance should be based on _featureEvaluator, if V2 flow then "newflow" should be instantiated else "old flow" instance
Why don't you just inject the dependency you need?
public class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IDataManager dataManager)
{
_dataManager = dataManager;
}
public void Execute()
{
_dataManager.Run();
}
}
In your Composition Root you can conditionally compose DataProcessor with the implementation of IDataManager you'd like:
public DataProcessor CreateDataProcessor()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
IDataManager dm = new NewFlow();
return new DataProcessor(dm);
}
IDataManager dm = new OldFlow();
return new DataProcessor(dm);
}
This seems to be similar to feature toggles. Why, by the way, is _featureEvaluator an interface? Wouldn't a bool suffice?
I am writing a wrapper for a dll. I'm using a factory pattern with a manager class for configuring purposes.
public sealed class Manager {
private static readonly factory = new Factory();
//prevents the default instance from being instantiated
private Manager(){}
public static IFoo GetMyIFoo(IParam param) {
return factory.GetMyIFoo(param);
}
}
Then my factory handles the instantiating configuration:
public class Factory {
public IFoo GetMyIFoo(IParam param) {
IFoo foo = new Foo(param);
foo.SetConfiguration(this.Configuration, this);
return foo;
}
}
In my parallel foreach:
Parallel.ForEach(fooThings, (fooThing, state) => {
using(var foo = Manager.GetMyIFoo(fooThing)) {
foo.MyDllMethods(); //throws an error in parallel
}
});
My code works fine in a vanilla foreach, but I'm getting AccessViolationException when ran under Parallel.ForEach:
Attempted to read or write protected memory. This is often an
indication that other memory is corrupt.
If I step through the error with F10, I get the best clue is from the DLL itself:
You can operate on an instance only in the thread which created it.
What is happening?
As I stated in my comment, foo.SetConfiguration(this.Configuration, this); I think 'this' is the problem. You are sharing an instance created by one thread with another thread since you have a static variable in the manager
public sealed class Manager
{
//prevents the default instance from being instantiated
private Manager() { }
public static IFoo GetMyIFoo(IParam param)
{
Factory factory = new Factory();
return factory.GetMyIFoo(param);
}
}
Plain and simple as the title suggests, is this a possible thing using Autofac dependency injection? I have been trying and searching everywhere.. I'm losing hope here.
My class has to be singleton - that can't change. I want it to take a factory of unit of works - for database transactions.
Please help me figure this one out, I'm deseperate.
Tried Func<> and registering my unit of work in every possible way (all sorts of lifetimes, externally owned or not) but failed because the DbContext within the unit of work is disposed and not created again after the first request
Edit:
Added code that will hopefully help understanding my problem:
public class SingletonDataService : IDataService
{
private _uowFactory;
public SingletonDataService(Func<IEFUnitOfWork> uowFactory)
{
_uowFactory = uowFactory
}
public List<Folder> GetAllFolders ()
{
using (uow = uowFactory())
{
return uow.FoldersRepository.GetAll();
}
}
}
public MyDbContext : DbContext
{
public DbSet<Folder> Folders {get; set;}
public DbSet<Letter> Letters {get; set;}
public MyDbContext() : base("myContext...")
}
public EFUnitOfWork : IEFUnitOfWork, IDisposable
{
public IRepository<Folder> FoldersRepository;
public IRepository<Letter> LettersRepository;
private DbContext _context;
public EFUnitOfWork(IRepository<Folder> folders, IRepository<Letter> letters, DbContext context)
{
_folders = folders;
_letters = letters;
_context = context;
}
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
_context.Dispose();
}
disposed = true;
}
}
}
public Repository<T> : IRepository<T> where T: BaseEntity
{
private DbContext _context;
private DbSet<T> _set
public Repository(DbContext context)
{
_context = context;
_set = _context.Set<T>();
}
}
public LettersController : ApiController
{
private IDataService _dataService;
public LettersController(IDataService dataService)
{
_dataService = dataService;
}
[HttpGet]
public IHttpActionResult GetAllLetters()
{
return Ok(_dataService.GetAllLetters());
}
}
// Must be singleton
builder.Register<SingletonDataService>().As(IDataService).SingleInstance();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.Register<EFUnitOfWork>().As(IEFUnitOfWork).InstancePerLifetimeScope();
builder.Register<DbContext>().As(AppDbContext).InstancePerLifetimeScope();
In the first request everything works fine, in the second third and so on I get this exception :
system.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I clearly see it happens because the context in my repository is now null, but I don't how to to change that with the DI.
What I want to achieve is so easy without DI :
How can I achieve the following with Autofac??
public class UowFactory
{
public UowFactory()
{
}
public IEFUnitOfWork Create()
{
var context = new AppDbContext()
var uow = new EFUnitOfWork(new Repository<Folder>(context), new Repository<Letter>(context), context);
return uow;
}
}
Issue
You are registering the critial components with InstancePerLifetimeScope()
When the autofac container is built it also creates a root ILifetimeScope which lives until IContainer.Dispose() is called. Now unless you create nested ILifetimeScope somewhere in the chain to the SingletonDataService, the ILifetimeScope which is used your components is the root ILifetimeScope and InstancePerLifetimeScope() effectly becomes equivalent to SingleInstance().
Solution
One of the possible solutions is to create an ILifetimeScope per IEFUnitOfWork and its children. Autofac facilitates this by providing the Owned<T> type. We can use it in conjunction with a Func<> factory (also see documentation):
public class SingletonDataService : IDataService
{
private Func<Owned<IEFUnitOfWork>> _uowFactory;
public SingletonDataService(Func<Owned<IEFUnitOfWork>> uowFactory)
{
_uowFactory = uowFactory
}
public List<Folder> GetAllFolders ()
{
using (var uow = _uowFactory())
{
return uow.Value.FoldersRepository.GetAll();
}
}
}
This should play nicely with the following registrations:
// Must be singleton
builder.Register<SingletonDataService>().As(IDataService).SingleInstance();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.Register<EFUnitOfWork>().As(IEFUnitOfWork).InstancePerLifetimeScope();
builder.Register<DbContext>().As(AppDbContext).InstancePerLifetimeScope();
However, note, that DbContext being bound with InstancePerLifetimeScope basically makes the manual disposal in EFUnitOfWork redundant.
Sidenote on proper Disposal
Since IDisposable types should support graceful multi-disposal , one should be able to simplify EFUnitOfWork.Dispose() to
public void Dispose()
{
_context.Dispose();
}
Also note, that i left out the call GC.SuppressFinalize(this);. This call is only relevant in case the class implements a custom finalizer (~EFUnitOfWork method) - or a deriving class could do so, otherwise the object is not put on the finalizer queue anyway.
Your problem is that you have a singleton (SingletonDataService) depend on a service that has a shorter lifetime (EFUnitOfWork). When the SingletonDataService instance is created by autofac, it gets an instance of EFUnitOfWork, but this instance will always stay the same (its actual lifetime will be longer than you expect) and thus gets disposed and used again, giving errors.
You have two possible solutions:
One is to create a UowFactory class like the one you defined at the bottom (but with dependencies on IRepository<Folder>, IRepository<Letter>, DbContext), register that as anything (for example singleton, but it won't matter) and make the SingletonDataService depend on it. This will likely not be a viable solution to you though, since it will also extend the lifetime of the IRepository<Folder>, IRepository<Letter>, DbContext instances and create problems there.
The proper solution is to remove the reason why you would want the SingletonDataService to be a singleton, probably some cache. And move it to a new service (CacheService?) on which the SingletonDataService depends and make that new service a singleton.
I have this class:
public class AutofacEventContainer : IEventContainer
{
private readonly IComponentContext _context;
public AutofacEventContainer(IComponentContext context)
{
_context = context;
}
public IEnumerable<IDomainEventHandler<T>> Handlers<T>(T domainEvent)
where T : IDomainEvent
{
return _context.Resolve<IEnumerable<IDomainEventHandler<T>>>();
}
}
The IEventContainer look like this:
public interface IEventContainer
{
IEnumerable<IDomainEventHandler<T>> Handlers<T>(T domainEvent)
where T : IDomainEvent;
}
Now this IEventContainer is used in a class DomainEvents like this:
public static class DomainEvents
{
....................................
....................................
public static IEventContainer Container;
public static void Raise<T>(T domainEvent) where T : IDomainEvent
{
if (Container != null)
foreach (var handler in Container.Handlers(domainEvent))
handler.Handle(domainEvent);
// registered actions, typically used for unit tests.
if (_actions != null)
foreach (var action in _actions)
if (action is Action<T>)
((Action<T>)action)(domainEvent);
}
}
My aim is to have the DomainEvents.Container registered so that all handlers are resolved.
public class SomeModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
//Wrong way in Autofac
//Because the following line is Ninject-like
DomainEvents.Container = new AutofacContainer(componentContext);
//What is the correct way to register it to achieve the above intent?
}
}
What is the way to do this in Autofac?
You are going to have a memory leak if you resolve out of the root scope. (See this post for a good overview of lifetime scopes in Autofac.) A better way to do it would be like this:
interface IEventRaiser
{
void Raise<TEvent>(TEvent #event) where TEvent : IDomainEvent;
}
class AutofacEventRaiser : IEventRaiser
{
private readonly ILifetimeScope context;
public AutofaceEventRaiser(ILifetimeScope context)
{
this.context = context;
}
public void Raise<TEvent>(TEvent #event) where TEvent : IDomainEvent
{
using(var scope = context.BeginLifetimeScope("eventRaiser"))
{
foreach(var handler in scope.Resolve<IEnumerable<IDomainEventHandler<TEvent>>>())
{
handler.Handle(#event);
}
} // scope is disposed - no memory leak
}
}
// then, in the composition root:
IContainer theContainer = BuildTheAutofacContainer();
DomainEvents.EventRaiser = new AutofacEventRaiser(theContainer);
This is the simple answer, but there is one more caveat you should be aware of...
The question is whether you really want to use a static IEventRaiser. DI purists will generally say, "no - you should inject an instance of your IEventRaiser into every class that needs one", but others have argued that a static event raiser is OK.
Be sure you are aware of how Autofac's lifetime scopes work before you make this decsion, because it could affect component sharing. For example, say SomeClass has an instance of SomeDependency and it raises SomeEvent. Let us also assume that SomeDependency is InstancePerLifetimeScope.
If SomeClass gets the IEventRaiser injected, then the handlers will be invoked on the same lifetime scope, and will be injected with the same instance of SomeDependency.
If SomeClass uses a static IEventRaiser, then the handlers will be invoked on a different lifetime scope, and will be injected with a different instance of SomeDependency.
You can see why this matters if you imagine that SomeDependency is something like a DB transaction.