NHibernate and Structure Map - nhibernate

So I really like working with NHibernate but always used Spring.Net with it.
I recently came across StructureMap by Jeremy Miller and really like it better than Spring.Net. On his StructureMap site he promises an example on how to use NHibernate and StructureMap together. Unfortunately he has not had time to do it (or I can't find it).
So does anyone have an example on how to handle the NHibernate Session with StructureMap?

So, I apologize that we did not get the NHibernate with StructureMap example done earlier. Eventually, I would like to publish it in the StructureMap documentation, but I need some feedback first. You can see the full example on my blog:
http://trason.net/journal/2009/10/7/bootstrapping-nhibernate-with-structuremap.html
That being said, I can hit the highlights here. There is an NHibernateRegistry that makes available four things: an NHibernate.Configuration (as a Singleton), an ISessionFactory (as a Singleton), an ISession (scoped Hybrid (HttpContext if available, falling back to Thread local storage)), and a very simple IUnitOfWork. Also, there is an HttpModule to manage the UnitOfWork per web request.
Here is the code for the NHibernateRegistry:
using NHibernate;
using NHibernate.ByteCode.Castle;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernateBootstrap.Core.Domain;
using StructureMap.Attributes;
using StructureMap.Configuration.DSL;
using Environment=NHibernate.Cfg.Environment;
namespace NHibernateBootstrap.Core.Persistence
{
public class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
var cfg = new Configuration()
.SetProperty(Environment.ReleaseConnections, "on_close")
.SetProperty(Environment.Dialect, typeof(SQLiteDialect).AssemblyQualifiedName)
.SetProperty(Environment.ConnectionDriver, typeof(SQLite20Driver).AssemblyQualifiedName)
.SetProperty(Environment.ConnectionString, "data source=bootstrap.sqlite;Version=3")
.SetProperty(Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName)
.AddAssembly(typeof(Blog).Assembly);
var sessionFactory = cfg.BuildSessionFactory();
ForRequestedType<Configuration>().AsSingletons().TheDefault.IsThis(cfg);
ForRequestedType<ISessionFactory>().AsSingletons()
.TheDefault.IsThis(sessionFactory);
ForRequestedType<ISession>().CacheBy(InstanceScope.Hybrid)
.TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<ISessionFactory>().OpenSession());
ForRequestedType<IUnitOfWork>().CacheBy(InstanceScope.Hybrid)
.TheDefaultIsConcreteType<UnitOfWork>();
ForRequestedType<IDatabaseBuilder>().TheDefaultIsConcreteType<DatabaseBuilder>();
}
}
}
Here is the code for the Unit of Work:
using System;
using NHibernate;
namespace NHibernateBootstrap.Core.Persistence
{
public interface IUnitOfWork : IDisposable
{
ISession CurrentSession { get; }
void Commit();
}
}
using NHibernate;
namespace NHibernateBootstrap.Core.Persistence
{
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
CurrentSession = _sessionFactory.OpenSession();
_transaction = CurrentSession.BeginTransaction();
}
public ISession CurrentSession { get; private set;}
public void Dispose()
{
CurrentSession.Close();
CurrentSession = null;
}
public void Commit()
{
_transaction.Commit();
}
}
}
Here is the NHibernateModule for web applications:
using System;
using System.Web;
using NHibernateBootstrap.Core.Persistence;
using StructureMap;
namespace NHibernateBootstrap.Web
{
public class NHibernateModule : IHttpModule
{
private IUnitOfWork _unitOfWork;
public void Init(HttpApplication context)
{
context.BeginRequest += ContextBeginRequest;
context.EndRequest += ContextEndRequest;
}
private void ContextBeginRequest(object sender, EventArgs e)
{
_unitOfWork = ObjectFactory.GetInstance<IUnitOfWork>();
}
private void ContextEndRequest(object sender, EventArgs e)
{
Dispose();
}
public void Dispose()
{
_unitOfWork.Dispose();
}
}
}

Does this help: http://devlicio.us/blogs/billy_mccafferty/archive/2007/02/05/inject-di-container-into-domain-objects-with-nhibernate.aspx

Edit here: I posted this comment before wbinford's answer was posted. I still think using NCommon is good, but his answer above is a little cleaner and does not require the use of another third party tool.
I really didn't get the answers I was looking for but I found a nice framework called NCommon. It implements the unit of work pattern along with the repository pattern with NHibernate, LinqToSql or the Entity Framework. It also handled the NHibernate ISession as well as configuration for NHibernate. I used the tool with StructureMap and NHibernate. I did have to get the service adapter for StructureMap, but once set up it works rather nicely.

Related

Confusion over using generic repository in .NET Core 6

I'm developing services with a micro service architecture using .NET Core 6. I'm trying to follow clean architecture advice and have created 3 layers, Core (I put my use cases, repository interfaces, and my dto models), API layer, and infrastructure (connection with DB and implementation of repository interfaces).
The problem is the number of repositories is increasing, because I'm creating a separate repository for each different job, for example IStoreCarPricesRepository, IStoreCarSparePartRepository,..... I was thinking, would it not be wiser to have a generic repository and and just create a class to call it and do the jobless say you are getting different messages from different queues and was to store them in the respective tables?
As far as I searched for generic repository is kind of outdated, I would appreciate your comments
Yes, you can use Generic repository:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.Entity;
using ContosoUniversity.Models;
using System.Linq.Expressions;
namespace DAL
{
public class GenericRepository<TEntity> where TEntity : class
{
internal SchoolContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(SchoolContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
}
Then you can instantiate and use it for each table:
private GenericRepository<Department> departmentRepository;
private GenericRepository<Employee> employeeRepository;
Read more about generic repositories here.
Repo doesn't works with jobs and messages.
The main responsibility of repository is a wrapper for common operations (CRUD) or maybe some work with tables for example count, any, some, all.
If you wish to create a microservice architecture, it is useful to check generic repositories in GitHub and create your own library and move the generic-repository here. It should be something like YourName.Microservice.Core.
After that, connect it through a nuget-extension to your Microservice.Core.
In the future, you need to extend them to avoid a duplication of code in a lot of microservices.

NHibernate Repository class - 1. Handle with Transaction | 2. How init session

Hi I start learn NHibernate and now I am trying create own repository class for NHibernate.
I found many articles about this thema. I chose this tutorial: http://dotnetslackers.com/Community/blogs/antrad/archive/2008/10/25/about-repository-pattern-and-nhibernate.aspx
I am little confuse how handle with transaction in repository.
I have repository interface:
public interface IRepository<T> where T : class
{
void Commit();
void RollBack();
void BeginTransaction();
//...
}
My question is why is good begin transaction in constructor class of repository.
This part of code is from blog on top.
public class NHibRepository<T> :IRepository<T>
where T : class
{
#region Private fields
private ISession _session;
#endregion
#region Constructor
public NHibRepository(ISession session)
{
_session = NHibernateSessionManager.Instance.GetSession();
//why begin transaction where???
_session.BeginTransaction();
}
#endregion
#region Trans
public void Commit()
{
if (session.Transaction.IsActive)
{
session.Transaction.Commit();
}
}
public void Rollback()
{
if (session.Transaction.IsActive)
{
session.Transaction.Rollback();
session.Clear();
}
}
public void BeginTransaction()
{
Rollback();
session.BeginTransaction();
}
#endregion
}
I update this repository and now I use this solution:
public class NHibRepository<T> :IRepository<T>
where T : class
{
#region Private fields
private ISession _session;
#endregion
#region Constructor
public NHibRepository(ISession session)
{
_session = session;
}
#endregion
#region Trans
public void Commit()
{
using (var trans=_session.BeginTransaction())
{
trans.Commit();
}
}
public void RollBack()
{
using (var trans = _session.BeginTransaction())
{
trans.Rollback();
}
}
public void BeginTransaction()
{
throw new NotImplementedException();
}
#endregion
}
My first question is which solution is better and why? or what is correct why?
And my second question is how open session for repository class, now I use this helper class:
public class NHibeHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
InitializeSessionFactory();
return _sessionFactory;
}
}
private static void InitializeSessionFactory()
{
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(
#"Server=Zues\SQLEXPRESS;Database=TEST;Trusted_Connection=True;")
)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserMap>().Conventions.Add(DefaultCascade.All()))
.ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(true, true))
.BuildSessionFactory();
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
On use like this:
_userRepo = new NHibRepository<User>(NHibeHelper.OpenSession());
Looking at the two options you've presented for transaction management, they both actually have issues.
In example 1, the transaction isn't necessarily disposed, and also you're linking the lifetime of the transaction to the lifetime of the repository. This isn't necessarily a bad thing but unless you're using an IoC container or some other method to ensure that the repository is recreated for each database operation, you will only be able to commit once, and subsequent commits will probably fail.
Example 2 will unfortunately not work at all - in Commit/RollBack you are starting a new transaction every time. Especially in the case of RollBack, if this was called from external code while in the context of a transaction, all you will do is start a new nested transaction and then immediately roll it back. Not very useful unfortunately.
My personal solution to your first question is to pull transaction management away from the repository by using the ambient transactions in System.Transactions. This way you still have separation as ambient transactions are provider-agnostic, but also you have more control about what of many repository operations you might be performing will be involved in the transaction, rather than always using the single-transaction-per-operation model. See http://msdn.microsoft.com/en-us/magazine/cc163527.aspx for more info.
As for your second question, I would highly recommend looking into an IoC container like Castle Windsor or Unity. The helper class you have there is far better than rebuilding the session factory and such every time, but by using an IoC container you can very easily ensure the lifetime of your session object is exactly what you want it to be. For instance, in a number of WCF Per-Call services I'm working on, I use Castle Windsor to ensure that the session is created (and injected into the repository) when the WCF operation begins, and is disposed (along with the repository) when it ends.

Does StructureMap have scoping corresponding to NInject's DefinesNamedScope/InNamedScope?

The problem I'd like to solve is sharing an ISessionProvider between IXyzRepositories (where ISessionProvider holds the current NHibernate ISession).
I'm tweaking the "Setting up session per presenter" recipe from NHibernate 3 Cookbook, and would like to keep StructureMap (brownfield project).
I think you would have to create a custom Lifecyle to do that, although I am not sure what exactly you are trying to accomplish...
To create a custom Lifecycle, you just have to implement the ILifecycle interface and the use it in your registration. Here is an example you can look at: http://blog.mikeobrien.net/2010/01/creating-structuremap-lifecycle-for-wcf.html.
In a web application I use Singleton for the sessionFactory and HybridHttpOrThreadLocalScoped for the session:
This is my structuremap registry:
public class NhibernateRegistry: Registry
{
public NhibernateRegistry()
{
For<ISessionFactory>()
.Singleton()
.Use(new NHibernateSessionFactory(connectionString).SessionFactory);
For<ISession>()
.HybridHttpOrThreadLocalScoped()
.Use(o => o.GetInstance<ISessionFactory>().CurrentSession);
}
}
My NHibernateSessionFactory is similar to SessionProvider class used in the book.
Everything is disposed at the end of the request (web app):
protected void Application_EndRequest(object sender, EventArgs e)
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
I use a generic repository:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly ISession _session;
public GenericRepository(ISession session)
{
_session = session;
}
public T Load(Guid Code)
{
return (_session.Load<T>(Code));
}
}
but you can easily change it with your own implementation.
I register the repository here:
public class RepositoriesRegistry : Registry
{
public RepositoriesRegistry()
{
For <Data.IRepository<Domain.Reminder, Guid>>()
.HybridHttpOrThreadLocalScoped()
.Use<Data.NH.Repository<Domain.Reminder, Guid>>();
}
}

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.

Controlling NHibernate ITransaction with StructureMap?

I'm using StructureMap as my IoC container and NHibernate as my ORM. I found an example online that shows how to have StructureMap build the ISessionFactory and the ISession so the Factory is a singleton and the Session is based on the HttpContext. This works great, but then I started using NH Profiler which told me I should always be explicitly using Transactions. So, I thought, why not let StructureMap handle that for me too? Using the code below, I got that all working fine, except, I don't know how/where to commit/rollback my transaction.
Here is how I initialize StructureMap:
ObjectFactory.Initialize(x =>
{
x.ForRequestedType<ISessionFactory>()
.CacheBy(InstanceScope.Singleton)
.TheDefault.Is.ConstructedBy(cfg.BuildSessionFactory);
x.ForRequestedType<ISession>()
.CacheBy(InstanceScope.Hybrid)
.TheDefault.Is.ConstructedBy(context => context.GetInstance<ISessionFactory>().OpenSession());
x.ForRequestedType<ITransaction>()
.CacheBy(InstanceScope.Hybrid)
.TheDefault.Is.ConstructedBy(context => context.GetInstance<ISession>().BeginTransaction());
x.Scan(y =>
{
y.TheCallingAssembly();
y.WithDefaultConventions();
});
});
All my repositories look like the following:
public UserRepository(ISession session, ITransaction transaction)
{
_session = session;
_transaction = transaction;
}
And a typical method inside a repository looks like:
public void Remove(int id)
{
Remove(_session.Get<User>(id));
}
What I'm trying to do is have all the methods that I call in one HttpContext share the same Session and Transaction. Is this possible or is this totally wrong and I'm barking up the wrong tree?
Thanks in advance!
-Dan
This issue was why I created a simple UnitOfWork that combines ISession and ITransaction.
In tests, I would write the following code:
var product = new Product {Name = "Apple", Category = "Fruits"};
using (var session = _sessionFactory.OpenSession())
using (var transaction = _session.BeginTransaction())
{
session.Save(product);
transaction.Commit();
}
when I really wanted:
var product = new Product {Name = "Apple", Category = "Fruits"};
using (var unitOfWork = new UnitOfWork(_sessionFactory))
{
unitOfWork.CurrentSession.Save(product);
unitOfWork.Commit();
}
Here is my unit of work implementation,
using NHibernate;
namespace NHibernateBootstrap.Core.Persistence
{
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
CurrentSession = _sessionFactory.OpenSession();
_transaction = CurrentSession.BeginTransaction();
}
public ISession CurrentSession { get; private set;}
public void Dispose()
{
CurrentSession.Close();
CurrentSession = null;
}
public void Commit()
{
_transaction.Commit();
}
}
}
As far as the when to call Commit() (either using ITransaction or UnitOfWork), I believe that it should be done explicitly before the end of your request. If you don't call it, then the UnitOfWork should clean itself up, but not commit. Alternatively, you could use an HttpModule to commit in an EndRequest handler.