How should you use UnitofWork pattern on my asp.net-mvc site (using nhibernate and ninject) - nhibernate

i have followed the pattern on this site to hook up ninject and nhibernate to my asp.net-mvc3 site.
Here is the code in my global.aspx.cs:
internal class ServiceModule : NinjectModule
{
public override void Load()
{
var helper = new NHibernateHelper(connectionString);
Bind<ISessionFactory>().ToConstant(helper.SessionFactory)
.InSingletonScope();
Bind<IUnitOfWork>().To<UnitOfWork>()
.InRequestScope();
Bind<ISession>().ToProvider(new SessionProvider())
.InRequestScope();
Bind<IIntKeyedRepository<FAQ>>().To<Repository<FAQ>>()
.InRequestScope();
}
the issue is that i now need to do Update() and Add() in my controllers;
I have this as my controller code:
public FAQController(IIntKeyedRepository<FAQ> faqRepository, IUnitOfWork unitOfWork)
{
_faqRepository = faqRepository;
_unitOfWork = unitOfWork;
}
[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateInput(false)]
public ActionResult AddFAQ(FAQ contact)
{
var c = new FAQ {Question = contact.Question, Answer = contact.Answer};
_faqRepository.Add(c);
_unitOfWork.Commit();
return RedirectToAction("Index");
}
my main question is that it feels wrong to pass in Iunitofwork in the constructor as many other actions don't need it. I only really need it for the actions where i do updates and inserts into my db. Since i am using ninject IOC on the link above it seems to say to pass this unitofwork object through IOC.
So, is there a better more optimized way to using the UnitOfWork pattern with IOC in asp.net-mvc that does call beingtransaction for every method in my controller.

An alternative way to handle transactions is to use an IActionFilter Open the transaction in OnActionExecuting and commit on OnActionExecuted
public class TransactionFilter : IActionFilter
{
private readonly ISession session;
private ITransaction transaction;
public TransactionFilter(ISession session)
{
this.session = session;
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
this.transaction = this.session.BeginTransaction();
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
try
{
if (this.transaction.IsActive)
{
if (filterContext.Exception == null)
{
this.transaction.Commit();
}
else
{
this.transaction.Rollback();
}
}
}
finally
{
this.transaction.Dispose();
}
}
}
Define an attribute to mark the actions that use a transaction:
[AttributeUsage(AttributeTargets.Method)]
public class TransactionAttribute : Attribute
{
}
Change your Ninject configuration:
internal class ServiceModule : NinjectModule
{
public override void Load()
{
var helper = new NHibernateHelper(connectionString);
Bind<ISessionFactory>().ToConstant(helper.SessionFactory)
.InSingletonScope();
Bind<ISession>().ToProvider<SessionProvider>().InRequestScope();
Bind(typeof(IRepository<>)).To(typeof(Repository<>));
Bind(typeof(IIntKeyedRepository<>)).To(typeof(Repository<>));
BindFilter<TransactionFilter>(FilterScope.Action, null)
.WhenActionMethodHas<TransactionAttribute>();
}
}
Finally change your controller:
public FAQController(IIntKeyedRepository<FAQ> faqRepository)
{
_faqRepository = faqRepository;
}
[Transaction]
[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
[ValidateInput(false)]
public ActionResult AddFAQ(FAQ contact)
{
var c = new FAQ {Question = contact.Question, Answer = contact.Answer};
_faqRepository.Add(c);
return RedirectToAction("Index");
}

I generally try to keep my generic IRepository implementation hidden inside the IUnitOfWork (see below).
My other recommendation is to pass a UnitOfWorkProvider or UnitOfWorkFactory to the constructor. That way you can register the transaction scope locally. This has the added benefit of being able to resolve the IRepository or ISession as you see fit, via dependency injection or manually.
using(var uow = this.UnitOfWorkProvider.New())
{
uow.Save<Faq>(myFaq);
}
Also make sure you in your IUnitOfWork.Dispose() you clean up the transaction and any data session objects / information you might have.

I prefer to only inject my unit of work into classes that actually use them. In most cases, the persistence classes (Repository in my case) are the only ones that need the unit of work. You want to make sure you maintain a clean separation of concerns. The controller doesn't need to know about the unit of work and shouldn't be coupled to it, either.
public class FaqRepository {
public FaqRepository(IUnitOfWork unitofWork) { ... }
public void CreateQuestion(Faq faq) {
unitOfWork.Save(faq);
unitOfWork.Commit();
}
}
If you're invoking your repository from your controller, inject the repository into your controller as follows:
public class FaqController {
public FaqController(IFaqRepository faqRepository) {...}
}
Does that make sense?

Related

Custom action filter unity dependency injection web api 2

I followed this article and got everything working except dependency inject (partially). In my project I am using unity and I am trying to create a custom Transaction attribute the purpose of which is to start a NHibernate transaction before the execution of an action and commit/rollback the transaction after the method execution.
This is the definition of my attribute:-
public class TransactionAttribute : Attribute
{
}
Following is the definition of my TransactionFilter
public class TransactionFilter : IActionFilter
{
private readonly IUnitOfWork _unitOfWork;
public TransactionFilter(IUnitOfWork uow) {
_unitOfWork = uow;
}
public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) {
var transAttribute = actionContext.ActionDescriptor.GetCustomAttributes<TransactionAttribute>().SingleOrDefault();
if (transAttribute == null) {
return continuation();
}
var transaction = uow.BeginTransaction();
return continuation().ContinueWith(t =>
{
try{
transaction.Commit();
return t.Result;
}
catch(Exception e)
{
transaction.Rollback();
return new ExceptionResult(ex, actionContext.ControllerContext.Controller as ApiController).ExecuteAsync(cancellationToken).Result;
}
}
}
}
And I have created a custom filter provider which uses unity to construct this filter.
public class UnityActionFilterProvider
: ActionDescriptorFilterProvider,
IFilterProvider
{
private readonly IUnityContainer container;
public UnityActionFilterProvider(IUnityContainer container)
{
this.container = container;
}
public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
foreach (IActionFilter actionFilter in container.ResolveAll<IActionFilter>())
{
// TODO: Determine correct FilterScope
yield return new FilterInfo(actionFilter, FilterScope.Global);
}
}
}
I register the UnityActionFilterProvider in UnityWebApiActivator (I am using Unity.AspNet.WebApi package) as follows
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
var resolver = new UnityDependencyResolver(container);
var config = GlobalConfiguration.Configuration;
config.DependencyResolver = resolver;
var providers = config.Services.GetFilterProviders();
var defaultProvider = providers.Single(i => i is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(IFilterProvider), defaultProvider);
config.Services.Add(typeof(IFilterProvider), new UnityActionFilterProvider(container));
}
The problem is everything works ok for the first request for any action but subsequent requests for the same action doesn't recreate the TransactionFilter which means it doesn't call the constructor to assign a new UOW. I don't think I can disable the action filter caching.
The only option I have got now is to use the service locator pattern and get UOW instance using container inside ExecuteActionFilterAsync which in my opinion kills the purpose of this and I am better off implementing custom ActionFilterAttribute.
Any suggestions ?
As far as I've been able to tell during the years, what happens in web application startup code essentially has Singleton lifetime. That code only runs once.
This means that there's only a single instance of each of your filters. This is good for performance, but doesn't fit your scenario.
The easiest solution to that problem, although a bit of a leaky abstraction, is to inject an Abstract Factory instead of the dependency itself:
public class TransactionFilter : IActionFilter
{
private readonly IFactory<IUnitOfWork> _unitOfWorkFactory;
public TransactionFilter(IFactory<IUnitOfWork> uowFactory) {
_unitOfWorkFactory = uowFactory;
}
// etc...
Then use the factory in the ExecuteActionFilterAsync method:
var transaction = _unitOfWorkFactory.Create().BeginTransaction();
A more elegant solution, in my opinion, would be to use a Decoraptor that Adapts the TransactionFilter, but the above answer is probably easier to understand.

Quartz.NET, NH ISession & Ninject Scope

I'm trying to implement a service that will run jobs based on Quartz.Net. The jobs may have dependencies like IRepository<> and the repository implementation will have a NHibernate ISession injected into it. (Quartz will be hosted in a Windows Service). Jobs are resolved via a IJob factory implementation that uses Ninject to resolve (currently wrapped in a IServiceLocator implementation).
Job Scope
I would like to be able to use Ninject to scope the ISession per Job so that there is one session created per job that may be used in multiple IRepository<>'s .
Not sure if this is possible but am wondering if anyone has experience with this?
Can I somehow use the Job context to create a Scope that is used by Kernel.InScope(???).
Quartz.Net IJobFactory:
public class JobFactory : IJobFactory
{
readonly IServiceLocator locator;
public JobFactory(IServiceLocator locator)
{
this.locator = locator;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
var jobDetail = bundle.JobDetail;
var jobType = jobDetail.JobType;
return (IJob)locator.Resolve(jobType);
}
catch (Exception e)
{
var se = new SchedulerException("Problem instantiating class", e);
throw se;
}
}
}
Ninject Bindings:
//Service Locator
Bind<IServiceLocator>().To<NinjectAdapter>();
//Quartz Bindings
Bind<IJobFactory>().To<JobFactory>();
//NHibernate Bindings
Bind<ISessionFactory>().ToMethod(ctx => ctx.Kernel.Get<NHibernateConfiguration>().BuildSessionFactory()).InSingletonScope();
Bind<ISession>().ToMethod(ctx => ctx.Kernel.Get<ISessionFactory>().OpenSession());// ToDo: Figure out how to scope session
//Repository Bindings
Bind(typeof (IRepository<>)).To(typeof (ReadWriteRepository<>));
Main Execution:
InitializeIoC();
scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = ServiceLocator.Resolve<IJobFactory>();
InitializeJobs();
scheduler.Start();
Example Job:
public class TestJob3 : IJob
{
private readonly IRepository<Customer> repo;
private readonly IRepository<Order> orderRepo;
public TestJob3(IRepository<Customer> repo, IRepository<Order> orderRepo)
{
//orderRepo and repo should have the same ISession
this.repo = repo;
this.oderRepo = orderRepo;
System.Diagnostics.Debug.WriteLine("Job 3 Created");
}
#region Implementation of IJob
public void Execute(IJobExecutionContext context)
{
System.Diagnostics.Debug.WriteLine("Job 3 Executing");
using (var scope = new TransactionScope())
{
var customer = repo.GetById(1);
customer.Name = "Blue Goats";
repo.Save(customer);
scope.Complete();
}
}
#endregion
}
** Repository Snippet: **
public class ReadWriteRepository<TEntity> : IRepository<TEntity> where TEntity : class, IRootEntity
{
private readonly ISession session;
public ReadWriteRepository(ISession session)
{
this.session = session;
}
public virtual TEntity GetById(int id)
{
var entity = session.Get<TEntity>(id);
return entity;
}
public virtual TEntity Save(TEntity entity)
{
session.SaveOrUpdate(entity);
return entity;
}
}
Thanks for taking the time!
Update
I ended up using Remo's suggestion and am using InCallScope():
Bind<ISession>().ToMethod(ctx => ctx.Kernel.Get<ISessionFactory>().OpenSession()).InCallScope();
The way I like to think of it (correct or not?) is everything from the "initial" get reuses the same items throughout the dependency tree
Use InCallScope
https://github.com/ninject/ninject.extensions.namedscope/wiki/InCallScope

NHibernate: How to inject dependency on an entity

NHibernate 3.2/Fluent NHibernate 1.3/StructureMap 2.6.3 -
Trying to follow DDD as an architectural strategy, I typically don't have dependencies on domain entities. However, I'm experimenting right now with adding more behavior to my domain entities so that they are not so anemic. Everything was going well until I hooked up NHibernate. I've got two issues:
NH requires a parameterless constructor and I'd rather not have a
ctor that shouldn't be used.
When NH tries to instantiate my entity, it needs to resolve my
dependencies but I haven't given NH anything with which it can do
that.
I've been reading on the web, but most (if not all) of the examples I have found are outdated (or just old). Even though the NH camp probably doesn't approve of what I'm doing, I'm looking for the NH way to do this.
The solution ended up an implementation of NHibernate's IInterceptor. It is actually a very simple implementation when you inherit from EmptyInterceptor and override JUST the Instantiate() and SetSession() methods. Here's my interceptor using StructureMap:
public class DependencyInjectionEntityInterceptor : EmptyInterceptor
{
IContainer _container;
ISession _session;
public DependencyInjectionEntityInterceptor(IContainer container)
{
_container = container;
}
public override void SetSession(ISession session)
{
_session = session;
}
public override object Instantiate(string clazz, EntityMode entityMode, object id)
{
if (entityMode == EntityMode.Poco)
{
var type = Assembly.GetAssembly(typeof (SomeClass)).GetTypes().FirstOrDefault(x => x.FullName == clazz);
var hasParameters = type.GetConstructors().Any(x => x.GetParameters().Any());
if (type != null && hasParameters)
{
var instance = _container.GetInstance(type);
var md = _session.SessionFactory.GetClassMetadata(clazz);
md.SetIdentifier(instance, id, entityMode);
return instance;
}
}
return base.Instantiate(clazz, entityMode, id);
}
}
Then, all you have to do is tell NHibernate to use your interceptor:
public FluentConfiguration GetFluentConfiguration(IContainer container)
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.FromConnectionStringWithKey("Database"))
.ShowSql())
.Mappings(m =>
m.AutoMappings.Add(AutoMap.AssemblyOf<SomeClass>()))
.ExposeConfiguration(x =>
x.SetInterceptor(new DependencyInjectionEntityInterceptor(container)));
}
When I was researching this, some suggested passing in the SessionFactory into the ctor of the interceptor class. Honestly, from a session management perspective, this approach would be better.
If you need additional dependencies in your entities don't use constructor injection. Instead create an additional parameter in the entity method.
Now you will ask yourself how do you get the dependency. For this you can use CommandHandlers and Commands. The command handler takes the dependency within its constructor and calls the method of the entity. In the UI you create a command message and send it to a command processor which is responsible for calling the correct command handler.
I hope my explanation is comprehensible to you.
Domain:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public void SendNotification(string message, INotifier notifier)
{
notifier.SendMessage(string.Format("Message for customer '{0}' ({1}): {2}", Name, Id, message));
}
}
The INotifier infrastructure component is passed through the method and not the constructor!
Infrastructure:
public interface INotifier
{
void SendMessage(string message);
}
class EmailNotifier : INotifier
{
public void SendMessage(string message)
{
// SmtpClient...
}
}
class SMSNotifier : INotifier
{
public void SendMessage(string message)
{
// SMS ...
}
}
Command and CommandHandler:
public class NotificationCommandHandler : ICommandHandler<NotificationCommand>
{
private readonly INotifier _notifier;
public NotificationCommandHandler(INotifier notifier)
{
_notifier = notifier;
}
public void Execute(NotificationCommand commandMessage)
{
commandMessage.Employee.SendNotification(commandMessage.Message, _notifier);
}
}
public class NotificationCommand
{
public string Message { get; set; }
public Employee Employee { get; set; }
}
The CommandHandler gets the INotifier through constructor injection. So you do not need to use your IoC Container like a ServiceLocator.
Usage i.e. in the UI in a controller:
public class Controller
{
private readonly IMessageProcessor _messageProcessor;
public Controller(IMessageProcessor messageProcessor)
{
_messageProcessor = messageProcessor;
}
public void SendNotification (Employee employee, string message)
{
var sendMailCommand = new NotificationCommand
{
Employee = employee,
Message = message
};
_messageProcessor.Process(sendMailCommand);
}
}
If you have questions about the command processor have a look at the mvccontrib project or ask a separate question.
Sorry my previous answer didn't address the specific question. I did some more research, and it looks like I have much more to learn about when and when not to use an anemic domain model. Regarding your question, I found this article to be very on topic. It is on java, not c#, but the principles are the same. Hope this helps.

Injecting my UnitOfWork into my Repository Constructor

Im very new but on a quest to learn nhibernate and DI with structuremap so am making an app to test everything out.
I am having some problems injecting my unitofwork into my base repository. I create a unitofwork on every request then either commit or rollback at the end. But when tryin to inject into my base repository its always null when i go to use it in my methods. More specifically i get this error: "Object reference not set to an instance of an object". Any ideas what im doing wrong and if this is the correct route i should be going?
Many thanks in advance.
Base Repository:
public abstract class Repository<T> : IRepository<T>
{
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
UnitOfWork = _unitOfWork;
}
public Repository() {}
public void Save(T obj)
{
_unitOfWork.CurrentSession.Save(obj);
}
}
StructureMap registry thats set in my application_start:
public class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
For<ISession>().HybridHttpOrThreadLocalScoped().Use(context => context.GetInstance<ISessionFactory>().OpenSession());
For<ISessionFactory>().Singleton().Use(NHibernateSessionFactory.GetSessionFactory());
}
}
Update:
The baserepository is inherited by specific repositorys ie ArticleRepository then im injecting that into my aspx pages on application_start. Then my aspx page inherits a basepage where the buildUp takes place. And i access the repository like this:
public IArticleRepository ArticleRepo { get; set; }
public void SaveThing()
{
ArticleRepo.Save(object);
}
This gets called on application_start:
public class Bootstrapper
{
public static void BootStrap()
{
ObjectFactory.Configure(x =>
{
x.AddRegistry<NHibernateRegistry>();
x.AddRegistry<WebRegistry>();
});
}
}
And in the webregistry:
For<IArticleRepository>().Use<ArticleRepository>();
There is a good chance your ArticleRepository doesn't have a constructor that takes an IUnitOfWork as a parameter make sure you have the following
public class ArticleRepository : Repository<Article>
{
public ArticleRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
...
}
Remember Strcuture map uses the greediest constructor on the class that it instantiates. Since your abstract repository class will never be instantiated it will not use its constructors. I would also suggest not having any default constructors if your classes need to have their dependencies injected that way. Less chance for errors that way.
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
UnitOfWork = _unitOfWork;
}
I think you mean to write
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
_unitOfWork = UnitOfWork;
}
You were assigning the local variable to the parameter instead of the parameter to the local variable.
Edit: Also you should write your parameter with a lowercase U 'unitOfWork' instead of 'UnitOfWork'

Problem with understanding Ninject Binding/Injection

In my MVC project, I have setup my MvcApplication_start() :
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
And have successfully bound an .To regarding my IProductsRepository to MySqlProductsRepository:
public class NinjectControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel = new StandardKernel(new MyServices());
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController) _kernel.Get(controllerType);
}
public class MyServices: NinjectModule
{
public override void Load()
{
Bind<IProductsRepository>().To<MySqlProductsRepository>();
}
}
}
But I am using NHibernate, and have a separate Session Factory class that has a GetSession() method that returns an ISession.
public static ISessionFactory SessionFactory = CreateSessionFactory();
private static ISessionFactory CreateSessionFactory()
{
var cfg = new Configuration().Configure(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nhibernate.config"));
cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionStringName, System.Environment.MachineName);
NHibernateProfiler.Initialize();
return cfg.BuildSessionFactory();
}
public static ISession GetSession()
{
return SessionFactory.GetCurrentSession();
}
I wanted to set it up so that my MySqlProductsRepository would be passed and ISession object by Ninject when it was created:
public class MySqlProductsRepository : IProductsRepository
{
private readonly ISession _session;
public MySqlProductsRepository(ISession session)
{
_session = session;
}
And my Controller would be handed a IProductsRepository instance:
public class AdminController : Controller
{
private readonly IProductsRepository _productsRepository;
public AdminController(IProductsRepository productsRepository)
{
_productsRepository = productsRepository;
}
MY PROBLEM:
I can't seem to figure out in my IoC container where I bind my IProductsRepository to my Repository, how to register an ISession, how to hand an ISession to my MyProductsRepository object when it is created, and hand an MyProductsRepository object to my Controller?
I have a couple of blog post I wrote that explain how to use Ninject in and ASP.NET MVC application. The application in the blog post uses the same technologies that you are using: Ninject, NHibernate, and MySql. I also am using a repository pattern. There are a lot of parallels between what you are doing and these posts.
http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
http://blog.bobcravens.com/2010/09/the-repository-pattern-part-2/
http://blog.bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/
Take a look. If you have questions, feel free to contact me.