I'm developing an ASP.NET MVC 5 Web API application with C#, .NET Framework 4.5.1, Entity Framework 6.1.1 and the latest version of Ninject (I have also installed Ninject.MVC5).
I'm learning how to implement dependency injection, and I think I have learned it, but I have a question. These are my interfaces and classes.
Unit of work interface:
public interface IUnitOfWork
{
void Commit();
}
Custom DbContext implementation (I use IUnitOfWork interface to allow DI):
public class EFDbContext : DbContext, IUnitOfWork
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
[ ... ]
}
public void Commit()
{
this.SaveChanges();
}
}
And this is how allow Dependency Injection with Ninject and Ninject.Web.Common.
I have a class, NinjectConfigurator, that adds bindings:
public class NinjectConfigurator
{
public void Configure(IKernel container)
{
// Add all bindings/dependencies
AddBindings(container);
// Use the container and our NinjectDependencyResolver as
// application's resolver
var resolver = new NinjectDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
private void AddBindings(IKernel container)
{
ConfigureLog4net(container);
container.Bind<IUnitOfWork>().To<EFDbContext>().InRequestScope();
container.Bind<IGenericRepository<User>>().To<GenericRepository<User>>();
}
private void ConfigureLog4net(IKernel container)
{
log4net.Config.XmlConfigurator.Configure();
var loggerForWebSite = LogManager.GetLogger("MattSocialNetworkWebApi");
container.Bind<ILog>().ToConstant(loggerForWebSite);
}
}
And finally, I have this on NinjectWebCommon:
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
var containerConfigurator = new NinjectConfigurator();
containerConfigurator.Configure(kernel);
}
I use .InRequestScope() because I want a EFDbContext instance per request.
My question is: When do I have to do EFDbContext.SaveChanges()? If I'm using one instance per request I think I have to save the changes at the end of the request, isn't it?
Where do I have to put EFDbContext.Commit()?
The way I do it, and have seen done other places, is to either commit in your business layer, or in your controller, after each transaction. That means sometimes SaveChanges() will be called more than once per request, but that shouldn't be a significant problem.
I've learned a lot from looking at the code for SocialGoal, which can be found here. It uses Autofac for DI, but it's the same principles as your own code. Maybe you can get some inspiration and answers there too.
Related
I am using ef core and I am trying to implement the repository pattern as part of best practices. But I am we bit confused on the context normally I would create the context in the and inject
HomeController(WarehouseDBContext _context)
I have created my unitOfWork Class as suggested by the docs here
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application#creating-the-unit-of-work-class
However I am tad confused. It's expecting options here which is normally handled on the controller.
My UnitOfWork class
public class WarehouseUnitOfWork : IDisposable
{
private WarehouseDBContext context = new WarehouseDBContext();
private WarehouseRepository<StockItem> stockRepository;
public WarehouseRepository<StockItem> StockRepoistry
{
get
{
if (this.stockRepository == null)
{
this.stockRepository = new WarehouseRepository<StockItem>(context);
}
return stockRepository;
}
}
public void Save()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
But here it is complain that it expect options which would I presume contain the connection string. I am trying to decouple my code from EF so that If I want to upgrade in the future will be easier. My WareshouseDBContext is describe below
As you can see it is expecting options. What should I pass through here?
namespace WareHouseDal.Dal {
public class WarehouseDBContext : IdentityDbContext<ApplicationUser> {
public WarehouseDBContext(DbContextOptions<WarehouseDBContext> options)
: base(options) {
}
public DbSet<WarehouseCrm> Warehouse { get; set; }
public DbSet<Company> Companies { get; set; }
}
}
When I used to create my context before I just used the singleton pattern of
private readonly WarehouseDBContext _context;
Is their something else I need to do to allow it to accept the creation of the context on the unit of work level.
Error being given is
You shouldn't create a DbContext manually. Why not injecting the DbContext in your UOW class? Then the DI will manage the life cycle of the db context. To be honest I am not a fan of adding a UOW wrapper around EF which already implements the UOW pattern.
I would recommend you to see both talks, it will change the way you structure apps forever:
https://www.youtube.com/watch?v=5OtUm1BLmG0&ab_channel=NDCConferences
https://www.youtube.com/watch?v=5kOzZz2vj2o&t=3s&ab_channel=NDCConferences
Another amazing talk about EF Core details: https://www.youtube.com/watch?v=zySHbwl5IeU&ab_channel=NDCConferences
If you want to stick with Repository pattern, please check Ardalis repository with a clear example: https://github.com/ardalis/CleanArchitecture
I agree Ardalis repository is a great tutorial/example, in case if anyone want a lite solution to implement the Repository and Unit of Work Patterns in EF 5/EF 6.
you may check out the below one, I tested it would work in EF Core 6
https://pradeepl.com/blog/repository-and-unit-of-work-pattern-asp-net-core-3-1/
I'm using SignalR 0.5.2 and I'm trying to get a DependencyResolver set up using Unity. I've written the simplest code I can. I have a hub that I'm trying to inject into which looks like this:
public class SimpleHub : Hub
{
private readonly ITestService _service;
public SimpleHub(ITestService service)
{
_service = service;
}
public void Update()
{
Clients.callback("Kevin");
}
}
and a DependencyResolver that looks like this:
public class UnityDependencyResolver : DefaultDependencyResolver
{
private readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
if (_container.IsRegistered(serviceType))
{
return _container.Resolve(serviceType);
}
return base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
if (_container.IsRegistered(serviceType))
{
return _container.ResolveAll(serviceType);
}
return base.GetServices(serviceType);
}
}
I register the dependency resolver in Global.asax
protected void Application_Start()
{
IUnityContainer container = new UnityContainer();
InitializeContainer(container);
SignalR.IDependencyResolver resolver = new UnityDependencyResolver(container);
GlobalHost.DependencyResolver = resolver;
RouteTable.Routes.MapHubs();
// more MVC stuff here
}
where InitializeContainer register the ITestService in Unity
The resolver "works" in that it's getting called for all the SignalR types, and if I leave my hub with a default constructor it all gets loaded. However the resolver never gets asked to resolve the ITestService interface.
I've also tried passing the resolver to MapHubs, still no luck. I've also tried property injection using the [Dependency] attribute and that didn't work either.
Do I need to register the resolver with MVC as well? (I have tried that by implementing both IDependecyResolver interfaces but get an exception telling me the resolver doesn't implement IServiceLocator)
So I've sort of fixed this. I wondered if the fact that the Hub was registered with the signalr container and the interface was registered with the Unity container was causing the issue. So I registered the Hub with Unity and then everything works.
This sort of makes sense as there are two containers.
Is this the standard behaviour?
In case someone else is wondering... I found a good SPA example that uses
SignalR 1.0.1
Unity 3
A bunch of other frameworks
The interesting thing is the way he create the container, the dependencies and everything else. Worth checking it out.
I'm using ASP.NET MVC3, and Ninject. I've set up the standard code implementation in "AppStart_NinjectMVC3.cs" that sets up the bindings and adds a kernel to the DependencyResolver like this:
public static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUserRepository>().To<UserRepository>();
...
}
public static void Start() {
IKernel kernel = new StandardKernel();
RegisterServices(kernel);
DependencyResolver.SetResolver(new NinjectServiceLocator(kernel));
}
All is working well in my controllers - dependencies are being resolved fine.
I'd like to be able to use Ninject and these bindings outside of controllers, and outside of the MVC stack. For example, I have a bunch of regular aspx pages in which I'd like to use my ninject kernel, and some code hanging off global.asax too.
Can I re-use my Ninject kernel in these other places, or do I need to also register a kernel in my Global.asax appstart?
The current development release found on http://teamcity.codebetter.com provides support for side a side usage of ordinary aspx pages, mvc and wcf. You might want to have a look at this.
Be aware this is a development version and it is not tested very well. Nevertheless, I think it should be pretty much stable. But as it is work in progress it the interface can change. Also I won't give a lot of support before I have written the Ninject 2.4 preview blog about this change.
You need
Ninject
Ninject.Web.Common
Ninject.Web
Ninject.Web.MVC3
I've used the Ninject MVC Extension within my ASP.NET MVC application.
Here is the manner in which I've achieved what I think you're trying to accomplish.
Global.asax.cs:
public class MvcApplication : NinjectHttpApplication
{
/// <summary>
/// Overridden Ninject method that is called once the application has started and is initialized
/// </summary>
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
// Tell the MVC Framework to use our implementation of metadataprovider.
ModelMetadataProviders.Current = new XXX.myNamespace.MetadataProvider();
// Tell the MVC Framework to use our CartModelBinder class
ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());
}
/// <summary>
/// Establish a reference to our DIFactory object
/// <remarks>
/// This application currently uses Ninject for dependency injection.
/// </remarks>
/// </summary>
/// <returns></returns>
protected override IKernel CreateKernel()
{
return DIFactory.GetNinjectFactory();
}
// snip... additional global.asax.cs methods
}
DIFactory.cs:
/// <summary>
/// This class is used as a container for dependency injection throughout the entire application
/// </summary>
public class DIFactory
{
public static IKernel _kernel = null;
/// <summary>
/// Method used to create a single instance of Ninject's IKernel
/// </summary>
/// <returns>IKernel</returns>
public static IKernel GetNinjectFactory()
{
if (_kernel == null)
{
var modules = new INinjectModule[]
{
new ServiceModule()
};
_kernel = new StandardKernel(modules);
}
return _kernel;
}
/// <summary>
/// Method used as a service locator for the IConfiguration interface
/// </summary>
/// <returns></returns>
public static IConfiguration CreateConfigurationType()
{
return _kernel.Get<IConfiguration>();
}
// snip....additional public static methods for all other Interafaces necessary
}
ServiceModule.cs:
/// <summary>
/// Configures how abstract service types are mapped to concrete implementations
/// </summary>
internal class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IConfiguration>().To<XXX.myNamespace.Configuration>();
// snip... all other bindings to interfaces
}
}
Use in other classes besides Controllers:
UserInteraction.cs:
public class UserInteraction : IUserInteraction
{
private IConfiguration configuration;
public bool SubmitFeedback(Feedback feedback)
{
try
{
this.configuration = DIFactory.CreateConfigurationType();
// snip additional logic...
}
catch(Exception ex)
{
// snip
}
}
}
I am using unity, entity framework 4 with POCO classes, repository pattern for DAL and services for Business Logic control.
I also want to use Unit of Work so I can package together CRUD operations which I perform on different services and then commit them all together.
My question is what would be the proper way to inject the Unit Of Work mechanism into my application using Microsoft Unity?
I understand that I can put the IUnitOfWork together with the repository on the constructor of the proper service and then if Unity mapping is specified it would auto initiate the proper instances, but this way I do not pass the global unit of work but rather create a new instance on each level, which can't be a smart way to do it (actually the repository is initiated even before the service).
What am I missing? (Attached is constructor code as I wrote it now of service and its repository).
U also understand that I can use Unity's ParameterOverrides method to take some global instance of Unit of Work (lets say from my aspx.cs file) and pass it into the service and then into the repository. But it seems a bit lame. Is this my only option?
Thanks
public class GenericRepository<T> : IUnitOfWorkRepository, IGenericRepository<T> where T : BaseEntity, IAggregateRoot
{
private IUnitOfWork _uow;
/// <summary>
/// Returns the active object context
/// </summary>
private ObjectContext ObjectContext
{
get
{
return ObjectContextManager.GetObjectContext();
}
}
public GenericRepository(IUnitOfWork uow)
{
_uow = uow;
}
//blahhhh...
public void Add(T entity)
{
_uow.RegisterNew(entity, this);
}
public void Delete(T entity)
{
_uow.RegisterRemoved(entity, this);
}
//.....blah blah....
public void PersistCreationOf(IAggregateRoot entity)
{
this.ObjectContext.AddObject(GetEntitySetName(), entity);
}
public void PersistUpdateOf(IAggregateRoot entity)
{
// Do nothing as EF tracks changes
}
public void PersistDeletionOf(IAggregateRoot entity)
{
this.ObjectContext.DeleteObject(entity);
}
}
public class CategoryRepository : GenericRepository<XComSolutions.FB.Domain.Model.Entities.Category>, ICategoryRepository
{
public CategoryRepository(IUnitOfWork uow)
: base(uow)
{ }
}
public class CategoryService : ICategoryService
{
public int myID {get; set;}
private ICategoryRepository _categoryRepository;
private IUnitOfWork _uow;
public CategoryService(ICategoryRepository categoryRepository,
IUnitOfWork uow)
{
_categoryRepository = categoryRepository;
_uow = uow;
}
public List<Category> GetAll()
{
return _categoryRepository.GetAll();
}
}
Define an IUnitOfWorkFactory and inject that in your services:
public class Service
{
private readonly IUnitOfWorkFactory factory;
public Service(IUnitOfWorkFactory factory)
{
this.factory = factory;
}
public void DoOperation()
{
using (UnitOfWork context = this.factory.CreateNew())
{
this.DoSomeStuff(context);
this.DoMoreStuff(context);
context.SubmitChanges();
}
}
}
What I think you need to do is to define unit of work factory. You register this factory with your DI container and you resolve for this factory every time you need your unit of work. Then you get unit of work from the factory, work with it and let it go. You often will see that you need your unit of work within a scope of single method or single class. This article discuss Unit of Work pattern in connection with Entity Framework: http://msdn.microsoft.com/en-us/magazine/dd882510.aspx
I have the following code in my ASP.NET project
public sealed class IoC
{
private static readonly IDependencyResolver resolver =
Service.Get("IDependencyResolver") as IDependencyResolver;
static IoC()
{
}
private IoC()
{
}
public static IDependencyResolver Container
{
get
{
return resolver;
}
}
}
public static class Service
{
public static object Get(string serviceName)
{
// Code to create and return instance...
}
}
Is IoC.Container going to be thread safe?
Initialization of static fields is thread-safe: that is, the .NET runtime guarantees that your field will be initialized only once in the program, no matter how many threads access it and in what order.
As Andrey points out, the Service.Get method itself needs to be thread-safe.
IoC itself looks ok, but the whole structure will not be thread-safe if resolver is not thread safe. If you want to have resolver per thread you can use attribute [ThreadStatic]