ObjectDisposedException when trying to use the DBContext inside an IDistributedEventHandler - dependency-injection

I have an ABP app where we are using the IDistributedEventHandle. In these handlers I want to use the custom repository that we have in the application. This repository inherits from the Volo EfCoreRepository. However when the event handlers are executed I get ObjectDisposedException on the primary DbContext. I'm assuming this is because its now being used outside of asp.net primary scope.
public class EventHander : IDistributedEventHandler<ClientCreatedEto>,
ITransientDependency
{
private readonly ICustomRepository _repository;
public EventHander (ICustomRepository repo)
{
_repository= repo;
}
public async Task HandleEventAsync(ClientCreatedEto eventData)
{
//error here
}
}
I have also tried taking a dependency on IServiceProvider declaring a new scope and resolving the repository that way but I get the same exception. How should the primary DBContext for the application be resolved in eventhandlers?

You can try to use IUnitOfWorkManager in the HandleEventAsync method to create a unit of work, and use repositoryin the unit of work.
using (var uow = _unitOfWorkManager.Begin())
{
// your _repository method code.
await uow.CompleteAsync();
}
Or use [UnitOfWork] attribute.
[UnitOfWork]
public virtual async Task HandleEventAsync(ClientCreatedEto eventData)
{
// your _repository method code.
}

Related

AddTransient service using info from request

I've got an app in asp.net core using the built-in DI framework. I'd like to add a per-request (i.e. transient) service to the provider, but I'd like to actually make use of the request in its construction.
services.AddTransient<IMyService>(provider => { ... });
That's the closest overload I can find, but the provider object doesn't have anything about the current request. Is there a way to achieve what I'm trying to do, without upgrading to a more robust DI framework?
As posted in the comments, you can inject the IHttpContextAccessor into your services and access it, if the HttpContext is the only thing you need.
public class MyService : IMyService
{
private readonly HttpContext context;
public MyService(IHttpContextAccessor httpContextAccessor)
{
if(IHttpContextAccessor==null)
throw new ArgumentNullException(nameof(httpContextAccessor));
context = httpContextAccessor.HttpContext;
}
}
However, if you need something that's only available in the controller or outside of HttpContext, you can create a factory and pass the parameters to the factory
public class MyServiceFactory : IMyServiceFactory
{
// injecting the HttpContext for request wide service resolution
public MyServiceFactory(IHttpContextAccessor httpContextAccessor) { ... }
public IMyService Create(IDependency1 dep1, IDependency2 dep 2, string someRuntimeConfig)
{
IServiceProvider provider = this.context.RequestServices;
var myService = new MyService(provider.GetService<ISomeRepository>(), dep1, dep2, someRuntimeConfig);
return myService;
}
}
and then inject the IMyServiceFactory to your classes where you'd need IMyService.

Property injection upon initializing object manually

When using Ninject property injection the following works only if the object is instantiated by the framework (not by developer in code) so that the injection works:
public class SomeController: Controller {
[Inject]
public DbContext db {get; set;}
...
}
However when the object has to be instantiated in the code by the developer the binding does not happen (I don't wanna say fail because it does not happen).
public class DataProvision {
[Inject]
public DbContext db {get; set;}
public List<T> GetList<T>() where T: class, new() {
return db.Set<T>().toList();
}
...
}
public class Test {
public static void Test(){
DataProvision dp = new DataProvision();
var getValue = dp.GetList<Person>();
}
}
Is it even supported by Ninject and if yes what is the solution.
Justification of why we are doing this: Switching between back-up databases and active DBs effortlessly in case emergency
This is expected behavior. The DI framework has no opportunity to inject anything if you new up your own instances. If your code has access to the DI bindings, set up a kernel and use it to instantiate your class:
public class Test {
public static void Test(){
var kernel = new StandardKernel(new YourDiModule());
DataProvision dp = kernel.Get<DataProvision>();
var getValue = dp.GetList<Person>();
}
}
Using the above strategy, you'll probably need to tweak your DI configuration a little so that your context gets disposed when you want it to. (Your web application is probably normally set up to dispose the context after each web request completes, and it doesn't look like your test code is set up to run in the same kind of environment.)
Otherwise, you'll need to manage the dependency injection by hand:
public class Test {
public static void Test(){
using (var context = new DbContext()) // or however you create contexts
{
DataProvision dp = new DataProvision();
dp.db = context;
var getValue = dp.GetList<Person>();
}
}
}

Unit of Work pattern implementation

I am creating an application with ASP.NET MVC and Entity framework code first. I am using repository and unit of work pattern with influence of from following link.
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Here I have question about the implementation of Unit Of Work in that link unit of work is implemented via directly writing entities in class itself like.
public class UnitOfWork : IDisposable
{
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
public GenericRepository<Department> DepartmentRepository
{
get
{
if (this.departmentRepository == null)
{
this.departmentRepository = new GenericRepository<Department>(context);
}
return departmentRepository;
}
}
}
Do you think that implementation is good enough because every time I add/remove entities I need to change my Unit of work class. I believe that Unit of work should not be dependent on entities. Because in my application based on Client feedback we are going to frequently add/remove entities.
I may sound stupid but let me know your views on that.
The Unit of Work pattern is already implemented in Entity Framework.
The DbContext is your Unit of Work.
Each IDbSet is a Repository.
using (var context = new SchoolContext()) // instantiate our Unit of Work
{
var department = context.Departments.Find(id);
}
There are a few flavors of the UnitOfWorkPattern. The one you are describing is a show everything, there is a hide everything approach as well. In the hide approach the unit of work references the DbContext.SaveChanges() method and nothing else; sounds like what you want.
public YourContext : DbContext, IContext{}
public interface IUnitOfWork{
void Commit();
}
public UnitOfWork : IUnitOfWork{
private readonly IContext _context;
//IOC should always inject the same instance of this, register it accordingly
public UnitOfWork(IContext context){
_context = context;
}
void Commit(){
// try catch the validation exception if you want to return the validations this
// way if your confident you've already validated you can put a void here or
// return the intfrom save changes make sure you handle the disposing properly,
// not going into that here you also may be doing other stuff here, have multiple
// "contexts" to save in a single transaction or we have contextProcessors that
// do stuff based on items in the context
_context.SaveChanges();
}
}
This leaves the issue of how you get your repositories into the classes that need them if you are not taking them from the UnitOfWork. This is best handled by an IOC framework. Again here there are a couple options. Once is to register the UnitOfWork as a single instance per request and have it injected into your custom Repository class.
public interface IRepository<T>
{
IQueryable<T> Records();
//other methods go here
}
public Repository : IRepository<T>
{
private IContext _context;
// same instance of context injected into the unit of work, this why when you Commit
// everything will save, this can get tricky if you start adding Add, Update and stuff
// but EF does have the support needed.
public Repository(IContext context)
{
_context = context;
}
public Records()
{
return _context.Set<T>();
}
}
public class SomeService : ISomeService{
private readonly _myObjectRepository;
public SomeService(IRepository<MyObject> myObjectRepository){
_myObjectRepository = myObjectRepository;
}
}
Personally I consider the IDbSet an sufficient abstraction so I no longer create repositories. In
order to inject the IDbSets from the context though you need to register them as instances that you
extract from the context in your IOC setup. This can be complex and depending on your skills you
could find yourself in the situation where you have to register each IDbSet which I know you are trying to avoid.
What's nice about using the IDbSet is you have access to simple methods like Add and can avoid some of the more complex parts of working with Entity and DbEntity in a generic sense.
public class SomeService : ISomeService {
private readonly _myObjectSet;
// requires specialized IOC configurations because you have to pull this instance from
// the instance of the context, personally don't know how to do this with a single
// registration so this has the same problem as having to add each new repository to the
// unit of work. In this case each new Entity I add to the context requires I add an IOC
// registration for the type.
public SomeService(IDbSet<MyObject> myObjectSet){
_myObjectSet= myObjectSet;
}
}
Try passing the SchoolContext to the GenericRepository:
public GenericRepository<T>
{
private SchoolContext _context;
public GenericRepository(SchoolContext context)
{
_context = context;
}
public Get(int id)
{
return _context.Set<T>().Find(id);
}
}
And use:
using(var context = new SchoolContext())
{
var departmentRepository = new GenericRepository<Department>(context);
var department = departmentRepository.Get(1);
}

Dependency on a service layer with Ninject and MVC

I've got a problem with a bog standard three tier project using MVC that I'm trying to use Ninject with. I've got a MemberRepository:
public class MemberRepository : IMemberRepository{
public bool Save(Member member){
//saves member
}
}
I then have my Service Layer:
public class MemberService : IMemberService{
public bool Register(string email){
//Do Stuff & Populate Member Object
_repo.Save(member);
}
}
Given I'll be using Ninject what is the best way of me setting up my AccountController. Should I pass in the MemberService to the constructor like so:
public class AccountController : Controller
{
IMemberService _memberService;
public AccountController(IMemberService memberService)
{
_memberService = memberService;
}
}
Or pass in the repository:
public class AccountController : Controller
{
IMemberService _memberService;
public AccountController(IMemberRepository memberRepo)
{
_memberService = new MemberService(memberRepo);
}
}
Or Both?
I originally had just a repository (no service layer) but I've had to implement a service layer and I'm not sure how I'd handle the 'dependency' when registering the kernal in my NinjectWebCommon.cs file. Which was originally just this:
kernel.Bind<IMemberRepository>().To<SqlMemberRepository>();
But now I'm wondering if I need to register the IMemberService and have the repo as some kind of parameter.
:s Feeling kind of lost. Hope I'm making sense and someone can help out.
I've never used Ninject, I've been using Unity, but the same principles exist so hopefully this might help.
The service layer is the thing that is exposed to the controller - the controller needs to know nothing about the underlying repository. The flow is as follows, and each layer doesn't know about the layers above it:
Controller -> Service > Repository
So I would go with option 1, and then inject the repository into the constructor of the service.
public class MemberService : IMemberService {
private readonly IMemberRepository _repo;
[Inject]
public MemberService (IMemberRepository repo){
this._repo = repo;
}
public bool Register(string email){
//Do Stuff & Populate Member Object
_repo.Save(member);
}
}
and
public class AccountController : Controller
{
private readonly IMemberService _memberService;
[Inject]
public AccountController(IMemberService memberService)
{
_memberService = memberService;
}
}
That example obviously uses constructor injection but you can use property/field injection if you want instead. When you register your dependencies, you'll have to register both:
kernel.Bind<IMemberRepository>().To<SqlMemberRepository>();
kernel.Bind<IMemberService>().To<MemberService>();

How to remove unit of work functionality from repositories using IOC

I have an application using ASP.NET MVC, Unity, and Linq to SQL.
The unity container registers the type AcmeDataContext which inherits from System.Data.Linq.DataContext, with a LifetimeManager using HttpContext.
There is a controller factory which gets the controller instances using the unity container. I set-up all my dependencies on the constructors, like this:
// Initialize a new instance of the EmployeeController class
public EmployeeController(IEmployeeService service)
// Initializes a new instance of the EmployeeService class
public EmployeeService(IEmployeeRepository repository) : IEmployeeService
// Initialize a new instance of the EmployeeRepository class
public EmployeeRepository(AcmeDataContext dataContext) : IEmployeeRepository
Whenever a constructor is needed, the unity container resolves a connection, which is used to resolve a data context, then a repository, then a service, and finally the controller.
The issue is that IEmployeeRepository exposes the SubmitChanges method, since the service classes DO NOT have a DataContext reference.
I have been told that the unit of work should be managed from outside the repositories, so it would seem I ought to remove SubmitChanges from my repositories. Why is that?
If this is true, does this mean that I have to declare an IUnitOfWork interface and make every service class dependent upon it? How else can I allow my service classes to manage the unit of work?
You shouldn't try to supply the AcmeDataContext itself to the EmployeeRepository. I would even turn the whole thing around:
Define a factory that allows creating a new unit of work for the Acme domain:
Create an abstract AcmeUnitOfWork that abstracts away LINQ to SQL.
Create a concrete factory that can allows creating new LINQ to SQL unit of works.
Register that concrete factory in your DI configuration.
Implement an InMemoryAcmeUnitOfWork for unit testing.
Optionally implement convenient extension methods for common operations on your IQueryable<T> repositories.
UPDATE: I wrote a blog post on this subject: Faking your LINQ provider.
Below is a step-by-step with examples:
WARNING: This will be a loooong post.
Step 1: Defining the factory:
public interface IAcmeUnitOfWorkFactory
{
AcmeUnitOfWork CreateNew();
}
Creating a factory is important, because the DataContext implement IDisposable so you want to have ownership over the instance. While some frameworks allow you to dispose objects when not needed anymore, factories make this very explicit.
Step 2: Creating an abstract unit of work for the Acme domain:
public abstract class AcmeUnitOfWork : IDisposable
{
public IQueryable<Employee> Employees
{
[DebuggerStepThrough]
get { return this.GetRepository<Employee>(); }
}
public IQueryable<Order> Orders
{
[DebuggerStepThrough]
get { return this.GetRepository<Order>(); }
}
public abstract void Insert(object entity);
public abstract void Delete(object entity);
public abstract void SubmitChanges();
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract IQueryable<T> GetRepository<T>()
where T : class;
protected virtual void Dispose(bool disposing) { }
}
There are some interesting things to note about this abstract class. The Unit of Work controls and creates the Repositories. A repository is basically something that implements IQueryable<T>. The repository implements properties that return a specific repository. This prevents users from calling uow.GetRepository<Employee>() and this creates a model that is very close to what you are already doing with LINQ to SQL or Entity Framework.
The unit of work implements Insert and Delete operations. In LINQ to SQL these operations are placed on the Table<T> classes, but when you try to implement it this way it will prevent you from abstracting LINQ to SQL away.
Step 3. Create a concrete factory:
public class LinqToSqlAcmeUnitOfWorkFactory : IAcmeUnitOfWorkFactory
{
private static readonly MappingSource Mapping =
new AttributeMappingSource();
public string AcmeConnectionString { get; set; }
public AcmeUnitOfWork CreateNew()
{
var context = new DataContext(this.AcmeConnectionString, Mapping);
return new LinqToSqlAcmeUnitOfWork(context);
}
}
The factory created a LinqToSqlAcmeUnitOfWork based on the AcmeUnitOfWork base class:
internal sealed class LinqToSqlAcmeUnitOfWork : AcmeUnitOfWork
{
private readonly DataContext db;
public LinqToSqlAcmeUnitOfWork(DataContext db) { this.db = db; }
public override void Insert(object entity)
{
if (entity == null) throw new ArgumentNullException("entity");
this.db.GetTable(entity.GetType()).InsertOnSubmit(entity);
}
public override void Delete(object entity)
{
if (entity == null) throw new ArgumentNullException("entity");
this.db.GetTable(entity.GetType()).DeleteOnSubmit(entity);
}
public override void SubmitChanges();
{
this.db.SubmitChanges();
}
protected override IQueryable<TEntity> GetRepository<TEntity>()
where TEntity : class
{
return this.db.GetTable<TEntity>();
}
protected override void Dispose(bool disposing) { this.db.Dispose(); }
}
Step 4: Register that concrete factory in your DI configuration.
You know self best how to register the IAcmeUnitOfWorkFactory interface to return an instance of the LinqToSqlAcmeUnitOfWorkFactory, but it would look something like this:
container.RegisterSingle<IAcmeUnitOfWorkFactory>(
new LinqToSqlAcmeUnitOfWorkFactory()
{
AcmeConnectionString =
AppSettings.ConnectionStrings["ACME"].ConnectionString
});
Now you can change the dependencies on the EmployeeService to use the IAcmeUnitOfWorkFactory:
public class EmployeeService : IEmployeeService
{
public EmployeeService(IAcmeUnitOfWorkFactory contextFactory) { ... }
public Employee[] GetAll()
{
using (var context = this.contextFactory.CreateNew())
{
// This just works like a real L2S DataObject.
return context.Employees.ToArray();
}
}
}
Note that you could even remove the IEmployeeService interface and let the controller use the EmployeeService directly. You don't need this interface for unit testing, because you can replace the unit of work during testing preventing the EmployeeService from accessing the database. This will probably also save you a lot of DI configuration, because most DI frameworks know how to instantiate a concrete class.
Step 5: Implement an InMemoryAcmeUnitOfWork for unit testing.
All these abstractions are there for a reason. Unit testing. Now let's create a AcmeUnitOfWork for unit testing purposes:
public class InMemoryAcmeUnitOfWork: AcmeUnitOfWork, IAcmeUnitOfWorkFactory
{
private readonly List<object> committed = new List<object>();
private readonly List<object> uncommittedInserts = new List<object>();
private readonly List<object> uncommittedDeletes = new List<object>();
// This is a dirty trick. This UoW is also it's own factory.
// This makes writing unit tests easier.
AcmeUnitOfWork IAcmeUnitOfWorkFactory.CreateNew() { return this; }
// Get a list with all committed objects of the requested type.
public IEnumerable<TEntity> Committed<TEntity>() where TEntity : class
{
return this.committed.OfType<TEntity>();
}
protected override IQueryable<TEntity> GetRepository<TEntity>()
{
// Only return committed objects. Same behavior as L2S and EF.
return this.committed.OfType<TEntity>().AsQueryable();
}
// Directly add an object to the 'database'. Useful during test setup.
public void AddCommitted(object entity)
{
this.committed.Add(entity);
}
public override void Insert(object entity)
{
this.uncommittedInserts.Add(entity);
}
public override void Delete(object entity)
{
if (!this.committed.Contains(entity))
Assert.Fail("Entity does not exist.");
this.uncommittedDeletes.Add(entity);
}
public override void SubmitChanges()
{
this.committed.AddRange(this.uncommittedInserts);
this.uncommittedInserts.Clear();
this.committed.RemoveAll(
e => this.uncommittedDeletes.Contains(e));
this.uncommittedDeletes.Clear();
}
protected override void Dispose(bool disposing)
{
}
}
You can use this class in your unit tests. For instance:
[TestMethod]
public void ControllerTest1()
{
// Arrange
var context = new InMemoryAcmeUnitOfWork();
var controller = new CreateValidController(context);
context.AddCommitted(new Employee()
{
Id = 6,
Name = ".NET Junkie"
});
// Act
controller.DoSomething();
// Assert
Assert.IsTrue(ExpectSomething);
}
private static EmployeeController CreateValidController(
IAcmeUnitOfWorkFactory factory)
{
return new EmployeeController(return new EmployeeService(factory));
}
Step 6: Optionally implement convenient extension methods:
Repositories are expected to have convenient methods such as GetById or GetByLastName. Of course IQueryable<T> is a generic interface and does not contains such methods. We could clutter our code with calls like context.Employees.Single(e => e.Id == employeeId), but that's really ugly. The perfect solution to this problem is: extension methods:
// Place this class in the same namespace as your LINQ to SQL entities.
public static class AcmeRepositoryExtensions
{
public static Employee GetById(this IQueryable<Employee> repository,int id)
{
return Single(repository.Where(entity => entity.Id == id), id);
}
public static Order GetById(this IQueryable<Order> repository, int id)
{
return Single(repository.Where(entity => entity.Id == id), id);
}
// This method allows reporting more descriptive error messages.
[DebuggerStepThrough]
private static TEntity Single<TEntity, TKey>(IQueryable<TEntity> query,
TKey key) where TEntity : class
{
try
{
return query.Single();
}
catch (Exception ex)
{
throw new InvalidOperationException("There was an error " +
"getting a single element of type " + typeof(TEntity)
.FullName + " with key '" + key + "'. " + ex.Message, ex);
}
}
}
With these extension methods in place, it allows you to call those GetById and other methods from your code:
var employee = context.Employees.GetById(employeeId);
What the nicest thing is about this code (I use it in production) is that -once in place- it saves you from writing a lot of code for unit testing. You will find yourself adding methods to the AcmeRepositoryExtensions class and properties to the AcmeUnitOfWork class when new entities are added to the system, but you don't need to create new repository classes for production or testing.
This model has of course some shortcomes. The most important perhaps is that LINQ to SQL isn't abstract away completely, because you still use the LINQ to SQL generated entities. Those entity contain EntitySet<T> properties which are specific to LINQ to SQL. I haven't found them to be in the way of proper unit testing, so for me it's not a problem. If you want you can always use POCO objects with LINQ to SQL.
Another shortcome is that complicated LINQ queries can succeed in test but fail in production, because of limitations (or bugs) in the query provider (especially the EF 3.5 query provider sucks). When you do not use this model, you are probably writing custom repository classes that are completely replaced by unit test versions and you will still have the problem of not being able to test queries to your database in unit tests. For this you will need integration tests, wrapped by a transaction.
A last shortcome of this design is the use of Insert and Delete methods on the Unit of Work. While moving them to the repository would force you to have a design with an specific class IRepository<T> : IQueryable<T> interface, it prevents you from other errors. In the solution I use myself I also have InsertAll(IEnumerable) and DeleteAll(IEnumerable) methods. It is however easy to mistype this and write something like context.Delete(context.Messages) (note the use of Delete instead of DeleteAll). This would compile fine, because Delete accepts an object. A design with delete operations on the repository would prevent such statement from compiling, because the repositories are typed.
UPDATE: I wrote a blog post on this subject that describes this solution in even more detail: Faking your LINQ provider.
I hope this helps.
If combining unit of work and repository patterns, some people advocate that UoW should be managed outside of repository so that you could create two repositories (say, CustomerRepository and OrderRepository) and pass them the same UoW instance ensuring that all the changes to the DB will be done atomically when you finally call UoW.Complete().
In a mature DDD solution however, there should not be need for both UoW and a repository. This is because is such a solution aggregate boundaries are defined is such a way, that there is no need of atomic changes involving more than one repository.
Does this answer your question?

Resources