I am implementing dependency injection using Unity and the Unity.Webforms bootstrapper. I have a DbFactory in my webforms application which initializes my DbContext, and I am wanting to create one instance of this factory per web request, so that my various services will update under the same unit of work.
My question is, does the Unity.Webforms bootstrapper take care of this for me? I believe the answer in this post is suggesting doing the following in order accomplish a single context per request.
container.RegisterType<IDbFactory,DbFactory>(new HierarchicalLifetimeManager());
Is this correct, and is it all I need to do? I'm worried that it is creating a single context per request, but that it is an application wide context (all users sharing the same context).
This probably isn't necessary, but just in case, here is the implementation code for my DbFactory.
public class DbFactory : Disposable, IDbFactory
{
MyDbContext dbContext;
public MyDbContext Init()
{
return dbContext ?? (dbContext = new MyDbContext());
}
protected override void DisposeCore()
{
if(dbContext != null)
{
dbContext.Dispose();
}
}
}
public class Disposable : IDisposable
{
private bool isDisposed;
~Disposable()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(!isDisposed && disposing)
{
DisposeCore();
}
isDisposed = true;
}
protected virtual void DisposeCore(){}
}
Related
I am building an ASP.net WebApi, and trying to use Entity alongside. I am following this guide.
Getting Started with ASP.NET Web API 2 (C#)
I am receiving a 500 internal server error using Fiddler. The JSON Exception message states ExceptionMessage=An error occurred when trying to create a controller of type 'LocationsController'. Make sure that the controller has a parameterless public constructor.
Here is the Controller.cs
[RoutePrefix("api/Locations")]
public class LocationsController : ApiController
{
// GET api/<controller>
private IlocationsRepository LocationsRepo;
public LocationsController(IlocationsRepository _repo)
{
if (_repo == null) { throw new ArgumentNullException("_repo"); }
LocationsRepo = _repo;
}
[HttpGet]
[Route("")]
public IEnumerable<Location> GetAll()
{
return LocationsRepo.GetAll();
}
}
I can't use a parameterless public constructor because I need to use the Database Repository that was created for Locations. I verified the issue was with the IlocationsRepository by doing the following.
When I replace the LocationsController constructor with no parameters , and declare a List<Location> within the controller, and use dummy data. I receive a 200 with all the json data correct.
Here is the start of the Global.asax.cs file
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
protected void Session_Start(object sender, EventArgs e)
{
}
}
It seems as if I need to do the dependency injection in the Global, but none of the guides had any information regarding this part.
For posterity here is the ContextDB cs
public class WebServerContext : DbContext
{
public WebServerContext() : base("WebServerContext") {}
public DbSet<Order> dOrders { get; set; }
public DbSet<Location> dLocations { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
For additional posterity, here is the Locations Repository.
public class LocationsRepository : IlocationsRepository
{
private z_Data.WebServerContext db = new z_Data.WebServerContext();
public void Add(Location item)
{
db.dLocations.Add(item);
}
public IEnumerable<Location> GetAll()
{
return db.dLocations;
}
}
As per Dependency Injection for Web Api tutorial on MSDN, you are missing the line to register the dependency resolver (a concrete class that implements System.Web.Http.IDependencyResolver) with Web Api. It acts like a bridge between your DI container and Web Api so it can resolve your constructor dependencies.
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container); // <- You need this
// Other Web API configuration not shown.
}
Of course, that assumes you are using Unity. If not, you should either use the DependencyResolver that came with your DI container or implement your own.
NOTE: With some DI containers, you also need to register all of your controllers explicitly.
I have WebForms project, and there I have WebApi controller.
How I can inject to controller constructor and to action filter constructor?
I have implemented IDependencyResolver and use it in Global.asax (GlobalConfiguration.Configuration.DependencyResolver), but it doesn't help:
on request controller says that there is no default constructor and filter on application start says that it does not contain a constructor that takes 0 arguments.
Moreover, i need singletone injection to action filter.
Thanks.
UPD
public class ScopeContainer : IDependencyScope
{
protected readonly IUnityContainer _container;
public ScopeContainer(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
return _container.IsRegistered(serviceType) ? _container.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.IsRegistered(serviceType) ? _container.ResolveAll(serviceType) : new List<object>();
}
public void Dispose()
{
_container.Dispose();
}
}
public class IoCContainer : ScopeContainer, IDependencyResolver
{
public IoCContainer(IUnityContainer container) : base(container)
{
}
public IDependencyScope BeginScope()
{
var child = _container.CreateChildContainer();
return new ScopeContainer(child);
}
}
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterInstance<ILogger>(new Logger());
unity.RegisterType<IRepository, DbRepository>();
config.DependencyResolver = new IoCContainer(unity);
}
private static void RegisterRoutes()
{
RouteTable.Routes.MapHttpRoute("ServiceApi", "api/{controller}/{action}");
}
}
I think this may be the way you are registering your routes.
WebApi routes are registered in the default project examples via the GlobalConfiguration.Routes rather than the RouteTable.Routes which is used by MVC controllers. If the ApiController is being incorrectly loaded by the MVC routing method it won't find your dependency resolver.
Try modifying your code to this:
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(GlobalConfiguration.Configuration);
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterInstance<ILogger>(new Logger());
unity.RegisterType<IRepository, DbRepository>();
config.DependencyResolver = new IoCContainer(unity);
}
private static void RegisterRoutes(HttpConfiguration config)
{
config.Routes.MapHttpRoute("ServiceApi", "api/{controller}/{action}");
}
}
I was having the same issue, I was working on a project trying to help modernize an old web forms project by converting page by page to Web API / Angular and getting the plumbing just right to use Unity was key.
When I was tracing I noticed unity was trying to resolve the controller classes but not the types to inject into their constructors, so I registered my controllers and it all worked. See my example below
Config setup, register controller and dependency
void ConfigureApi(HttpConfiguration config)
{
var container = UnitySingleton.UnityContainer;
container.RegisterType<IDashboardManager, ExampleStuff>();
container.RegisterType<DashboardController>(new InjectionConstructor(container.Resolve<IDashboardManager>()));
config.DependencyResolver = new UnityIoCContainer(container);
}
And my controller example:
public class DashboardController : ApiController
{
private readonly IDashboardManager _dashboardManager;
public DashboardController(IDashboardManager dashboardManager)
{
_dashboardManager = dashboardManager;
}
public async Task<IEnumerable<string>> Get()
{
return await _dashboardManager.GetDatas();
}
}
This is how I got mine working. It was a little different than the article above.
I'm starting a new ASP.NET project, and I'm trying to follow the multi-project approach I've seen mentioned in multiple questions around Stackoverflow.
I've been following this tutorial, but it assumes only one project for your entire solution. Most notably, it recommends modifying your Global.asax file with code to set the database initializer.
Seeing as how my DAL project doesn't have a Global.asax file, what is the correct procedure for seeding the initial EF database?
I stand corrected in my above comment that you would have access to the DAL by secondary reference. If you are truly wanting to keep from referencing the DAL in your web project, create a Bootstrapper class in your BLL that does the database stuff for you
The examples are pulled from the following blog post: http://weblogs.asp.net/rashid/archive/2009/02/17/use-bootstrapper-in-your-asp-net-mvc-application-and-reduce-code-smell.aspx
Create a bootstrap interface
public interface IBootstrapperTask
{
void Execute();
}
Create a class that would handle your database configuration
public class InitializeDatabase : IBootstrapperTask
{
public void Execute()
{
Database.SetInitializer(new Configuration());
using (var db = new Context())
{
try
{
db.Database.Initialize(false);
}
catch (DataException ex)
{
}
catch (Exception ex)
{
throw;
}
}
}
}
Create a static class that will execute the tasks (you can have more than one, registering routes could be moved to a BootstrapperTask)
public static class Bootstrapper
{
static Bootstrapper()
{
ConfigureContainer();
}
public static void Run()
{
var tasks = ServiceLocator.Current.GetAllInstances<IBootstrapperTask>();
foreach(var task in tasks)
{
task.Execute();
}
}
private static void ConfigureContainer()
{
IUnityContainer container = new UnityContainer();
UnityConfigurationSection configuration = (UnityConfigurationSection) ConfigurationManager.GetSection("unity");
configuration.Containers.Default.Configure(container);
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
}
}
Finally, your global.asax would have a one liner
protected void Application_Start()
{
Bootstrapper.Run();
}
There are some web.config things to do as well that you will see in the blog posting. Also, this question can lend some more information on the specifics of disposing, etc. There are more benefits to boostrapping than simply not having to reference a DAL with some excellent posts around the community on why using this pattern is a good thing as well as a few different approaches on implementation.
In the Application_Start of the Global.asax:
Database.SetInitializer(new Configuration());
using (var db = new Context())
{
try
{
db.Database.Initialize(false);
}
catch (DataException ex)
{
}
catch (Exception ex)
{
throw;
}
}
Where the Context class lives in the DAL:
public class Context : DbContext
{
public Context() : base("YourDatabaseName") { }
public DbSet<Employee> Employees { get; set; }
// ...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new EmployeeMap());
You do the mapping in a dedicated class public class EmployeeMap : EntityTypeConfiguration<Employee>.
Seeding is done in the DAL:
public sealed class Configuration : DropCreateDatabaseAlways<Context>
{
protected override void Seed(Context context)
{
// Do your seeding here
}
}
In an effort to make my entities persistent ignorant and make my repositories testable, I've implemented a repository pattern like so:
public interface IJobRepository : IRepository<Job>
{
Job GetJobById(int jobId); //Special case where I'm eager loading other entities
void SaveJob(Job job, Job originalJob);
}
public class JobRepository : IJobRepository
{
private readonly IContext _context;
public JobRepository()
{
_context = new CustomObjectContext();
}
public JobRepository(UnitOfWork unitOfWork)
{
_context = unitOfWork.Context;
}
//Basic GetAll, GetById, Add and Delete methods from IRepository<T> Interface here
//omitted for brevity
public Job GetJobById(int jobId)
{
var job = _context.Jobs.Include("Company").Include("Location").
Include("PlantInfo").Where(j => j.Jobid == jobId).SingleOrDefault();
_context.DisposeContext();
return job;
}
public void SaveJob(Job job, Job originalJob)
{
if (job.Jobid > 0)
{
// Update
_context.Jobs.Attach(originalJob);
_context.PlantInfoes.Attach(originalJob.PlantInfo);
_context.Jobs.ApplyCurrentValues(job);
_context.PlantInfoes.ApplyCurrentValues(job.PlantInfo);
Note: ApplyCurrentValues is an extension method I'm using on the ObjectSet
}
else
{
// Create
_context.Jobs.AddObject(job);
}
_context.Save();
}
}
public class UnitOfWork
{
private readonly IContext _context;
public UnitOfWork()
{
_context = new CustomObjectContext();
}
public UnitOfWork(IContext context)
{
_context = context;
}
public string Save()
{
return _context.Save();
}
internal IContext Context
{
get { return _context; }
}
}
public interface IContext
{
IObjectSet<Job> Jobs { get; }
IObjectSet<Company> Companies { get; }
IObjectSet<Location> Locations { get; }
IObjectSet<PlantInfo> PlantInfoes { get; }
string Save();
}
My ObjectContext inherits from IContext...So my understanding is that I will only use the overloaded constructor on the repository to facilitate unit tests or to use it in the case that I want to use the same context (not desirable based on this post I found on SO "Entity Framework and Connection Pooling" -- Is this right?
Also, assuming the context only gets disposed when the repository is garbage collected, I have to dispose the context explicitly to avoid the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker." exception when attaching the entity prior to a save.
That said, what is the best practice for managing the DataContext in a manner that keeps your entities persistent ignorant and repositories testable?
Note: This is an asp.net webapplication; UnitOfWork and IContext implementation was based on examples from "Programming Entity Framework", Second Edition by Julia Lerman Ch24.
Thanks in advance!
Firstly, I would ensure that whatever my "consumable" object is (either repository or unit of work, depending on your setup) implements IDisposable. When your consumbed object is disposed of, then you would dispose your underlying context.
For instance, if you're using your UnitOfWork as the consumable object (the one that gets created and called in your application), it would look something like:
public class UnitOfWork : IDisposable
{
// All the other stuff you had before plus:
public void Dispose ()
{
if (_context != null)
{
_context.Dispose ();
}
}
}
(Note: This can also be done on your repositories if they're the ones being consumed directly)
And then, you have a few options in your application. If you are going to use the UnitOfWork directly, you can use it like:
public void SomeMethodThatAccessesYourData ()
{
using (var unitOfWork = new UnitOfWork (/*Load in the context*/))
{
// Access your data here.
}
}
Or, in your Web Forms or MVC object you can use constructor injection and dispose of it when the Web Forms or MVC object is disposed of:
// If you're using MVC:
public class MyController : Controller
{
private UnitOfWork _unitOfWork;
public MyController (UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public override Dispose (bool Disposing)
{
if (Disposing && _unitOfWork != null)
{
_unitOfWork.Dispose ();
}
}
}
The same idea stands for a web forms Page.
The main reason for using the constructor overload is for Inversion of Control (IOC). It helps with both unit testing and with production code when used with an IoC Container. WebForms doesn't lend itself well to IoC, but it is really easy with MVC.
Edit
I don't really see the connection with your repositories and the unit of work. Usually you access the repositories from a unit of work or, in other implementations, you request a unit of work from your target repository. In your implementation (which I understand is not your own) there seems to be no need for both.
Edit 2
If the UoW is overkill for your application, and you know you can use IoC to inject your IContext, and you don't have very many repositories, you can do something like:
public IRepository<T> : IDisposable { }
public IJobRepository : IRepository<Job> { /* All the stuff you put here */ }
public JobRepository : IJobRepository
{
private IContext _context;
...
public void Dispose ()
{
if (_context != null)
{
_context.Dispose ();
}
}
public JobRepository (IContext context)
{
_context = context;
}
}
Then, how you use it depends on your specific task. I'm not a fan of this direct use of IRepository, but this answer is getting too long.
I have the Global.asax like the code below:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
// ....
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(typeof(IOCControllerFactory));
}
}
public class IOCControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public IOCControllerFactory()
{
kernel = new StandardKernel(new NanocrmContainer());
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return base.GetControllerInstance(requestContext, controllerType);
var controller = kernel.TryGet(controllerType) as IController;
if (controller == null)
return base.GetControllerInstance(requestContext, controllerType);
var standartController = controller as Controller;
if (standartController is IIoCController)
((IIoCController)standartController).SetIoc(kernel);
return standartController;
}
class NanocrmContainer : Ninject.Modules.NinjectModule
{
public override void Load()
{
// ...
Bind<DomainModel.Entities.db>().ToSelf().InRequestScope().WithConstructorArgument("connection", "Data Source=lims;Initial Catalog=nanocrm;Persist Security Info=True;User ID=***;Password=***");
}
}
}
In this case if somewhere it is the class, defined like:
public class UserRepository : IUserRepository
{
private db dataContext;
private IUserGroupRepository userGroupRepository;
public UserRepository(db dataContext, IUserGroupRepository userGroupRepository)
{
this.dataContext = dataContext;
this.userGroupRepository = userGroupRepository;
}
}
then the dataContext instance is created (if no one was created in this request scope) by Ninject.
So the trouble now is - where to invoke dataContext method .Dispose()?
UPD:
so i followed the advice from KeeperOfTheSoul and solved the issue in such way:
public override void ReleaseController(IController controller)
{
base.ReleaseController(controller);
var db = kernel.Get<DomainModel.Entities.db>();
db.Dispose();
}
A good place to handle this is in IControllerFactory.ReleaseController, eg
public override void ReleaseController() {
base.ReleaseController();
//Do whatever you need to clean up the IoC container here
}
In NInject this could be handled by scoping using an activation block, at the start of the request when creating the controller you can store the activation block in the HttpContext's current items, during ReleaseController you can retrieve the previously created activation block and dispose it.
You could also consider using InScope and having the custom scope implement INotifyWhenDisposed. After that the usage is the same as with an activation block, except now you store the scope in the HttpContext's current items.
A pattern that is sometimes used to dispose db connections is to call Dispose from the finaliser.
public class db : IDisposable {
//called by the garbage collector
~db() {
//Call dispose to make sure the resources are cleaned up
Dispose(false);
}
//IDisposable implementation
public void Dispose() {
Dispose(true);
}
//subclasses of db can override Dispose(bool) and clean up their own fields
protected virtual void Dispose (bool disposing) {
if (disposing) {
//Supress finalization as all resources are released by this method
//Calling Dispose on IDisposable members should be done here
GC.SupressFinalize();
}
//Clean up unmanaged resources
//Do not call other objects as they might be already collected if called from the finalizer
}
}
You could hook it into Application_EndRequest.