Reputation: 780
Repositiory, OrderRequestRepository.cs
public OrderRequestRepository(IntranetApplicationsContext context, ILogger logger)
{
_context = context;
_logger = logger;
}
...CRUD Methods
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_context.Dispose();
}
GC.SuppressFinalize(this);
}
Unity.WebApi UnityConfig.cs
container.RegisterType<IOrderRequestRepository, OrderRequestRepository>(new InjectionConstructor(new IntranetApplicationsContext() , new ElmahLogger()));
With the above line in UnityConfig.cs the first call to the api works, the second call fails with the error :
The operation cannot be completed because the DbContext has been disposed.
If I comment out the _context.Dispose() line, then it works, which is fine as Garbage Collection will clean up for me, but ideally I'd like to manage it myself.
Alternatively, if I use the below lines instead - without the InjectionConstructor - in the UnityConfig.cs then it also works fine.
container.RegisterType<ILogger, ElmahLogger>();
container.RegisterType<IOrderRequestRepository, OrderRequestRepository>();
But I want use the InjectionConstructor as I want to add another parameter to the OrderRequestRepository Constructor and manage the disposal. Any suggestions as to why doing both causes the error?
Update
I removed the IDisposable code, as suggested by Steven, and because
The general rule is that the one who creates an object should destroy it, so I'll leave my EF dbcontext (IntranetApplicationsContext) alone.
An IOC container (Unity.Webapi in my case) should handle disposal
So with this line in UnityConfig
container.RegisterType<IOrderRequestRepository, OrderRequestRepository> (new InjectionConstructor(new IntranetApplicationsContext(), new ElmahLogger()));
Reads with EF are working, but interestingly when I try an edit I get the following error:
Attaching an entity of type 'IntranetApplications.Infrastructure.Models.OrderRequest' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
If I roll back and use the basic line in the UnityConfig
container.RegisterType<IOrderRequestRepository, OrderRequestRepository>();
... everything works. I believe both lines are using the the same default lifetime manager, TransientLifetimeManager, so it's odd that using InjectionConstructor still seems to break things.
Upvotes: 1
Views: 1400
Reputation: 780
I've got around this, rather than fix the error:
I was using InjectionConstructor so I could pass multiple parameters, but as an alternative I have changed it so that I pass a single parameter, a Factory object to the repository instead.
public class OrderRequestRepository : IOrderRequestRepository
{
private readonly IntranetApplicationsContext _context;
private readonly ILogger _logger;
public OrderRequestRepository(IOrderRequestRepositoryFactory respositoryFactory)
{
_context = respositoryFactory.CreateIntranetApplicationsContext();
_logger = respositoryFactory.CreateLogger();
}
...
}
Factory
public interface IOrderRequestRepositoryFactory
{
ILogger CreateLogger();
IntranetApplicationsContext CreateIntranetApplicationsContext();
}
public class OrderRequestRepositoryFactory : IOrderRequestRepositoryFactory
{
public ILogger CreateLogger()
{
return new ElmahLogger();
}
public IntranetApplicationsContext CreateIntranetApplicationsContext()
{
return new IntranetApplicationsContext();
}
}
UnityConfig
container.RegisterType<ILogger, ElmahLogger>();
container.RegisterType<IOrderRequestRepository, OrderRequestRepository>();
container.RegisterType<IOrderRequestRepositoryFactory, OrderRequestRepositoryFactory>();
This works in that, I am not using the InjectionConstructor, so don't get the associated errors and can still pass as many parameters as I want, by using my Factory.
Upvotes: 1
Reputation: 172835
The problem here is that your OrderRequestRepository
is disposing stuff it doesn't own. The IntranetApplicationsContext
is injected into the repository and since the OrderRequestRepository
has no idea what the lifestyle of that dependency is, it cannot dispose it.
You probably registered the IntranetApplicationsContext
to have a per-request lifestylem while your repository is transient.
Solution: only implement IDisposable if you have anything to dispose itself. In your case that means that your repository doesn't need to IDisposable at all.
Upvotes: 1