An invalid or incomplete configuration was used while creating a SessionFactory - nhibernate

and here is the inner exception at the end :
Could not load file or assembly 'ByteCode.Castle' or one of its dependencies. The system cannot find the file specified.
I am adding all references for nhibernate , used all the builds here is my code :
using NHibernate;
using FluentNHibernate;
using NHibernate.Cfg;
using System.Reflection;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Cfg;
using NHibernate.ByteCode.Castle;
using Castle.Core;
using Castle.DynamicProxy;
namespace _3adaseh
{
public static class NHibernateHelper
{
private static void ReferByteCode()
{
//Just to make sure the ByteCodeCastle is loaded
ProxyFactory fake = new ProxyFactory();
}
#region Session
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
ReferByteCode();
var configuration = new Configuration();
#region Configuring Fluent NHibernate
IPersistenceConfigurer persistenceConfigurer = MsSqlConfiguration.MsSql2008.ConnectionString("Data Source=.;Initial Catalog=3adaseh;Integrated Security=True").ShowSql().ProxyFactoryFactory("ByteCode.Castle.ProxyFactoryFactory, ByteCode.Castle");
//
// initialize nhibernate with persistance configurer properties
//Configuration cfg = persistenceConfigurer.ConfigureProperties(new Configuration());
//var persistenceModel = new PersistenceModel();
//persistenceModel.AddMappingsFromAssembly(Assembly.Load("3adaseh.Mappings"));
//persistenceModel.Configure(cfg);
try
{
_sessionFactory = Fluently.Configure().Database(persistenceConfigurer).Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("3adaseh.Mappings"))).BuildSessionFactory();
}
catch (System.Exception ex)
{
throw ex;
}
//cfg.SetProperty(
// add mappings definition to nhibernate configuration
//try
//{
// var persistenceModel = new PersistenceModel();
// persistenceModel.AddMappingsFromAssembly(Assembly.Load("3adaseh.Mappings"));
// persistenceModel.Configure(cfg);
// _sessionFactory = configuration.BuildSessionFactory();
//}
//catch (System.Exception ex)
//{
// throw ex;
//}
#endregion
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
#endregion
#region CRUD Operations
public static void Add<T>(T newObject)
{
using (ISession session = NHibernateHelper.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(newObject);
transaction.Commit();
}
}
}
public static void Update<T>(T updatedObject)
{
using (ISession session = NHibernateHelper.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Update(updatedObject);
transaction.Commit();
}
}
}
public static void Remove<T>(T deletedObject)
{
using (ISession session = NHibernateHelper.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Delete(deletedObject);
transaction.Commit();
}
}
}
public static T GetById<T>(int objectID)
{
using (ISession session = NHibernateHelper.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
return session.Get<T>(objectID);
}
}
}
#endregion
}
}
I couldnt test anything so far , I am really getting bored of this error , I added nhibernate references to all my class libraries and nothing is being fixed , can anyone help please??

Make sure that you have assembly references to NHibernate.ByteCode.Castle.dll and Castle.Core.dll (and Castle.DynamicProxy2.dll if you're using NH2.1.2)* to ensure that it is copied into the output directory. Which version of Fluent NHibernate and NHibernate are you using?
* Castle.DynamicProxy2.dll was merged with Castle.Core.dll. The newer merged version of Castle.Core.dll is used in NH3.

Yes, exactly what James said. Since the proxy factory is only specified in the config for NHibernate and not actually used by any of the class libraries in a solution, it doesn't (always) get copied to the application project on build.
What works for me is to only reference the bare minimum in all the class libraries, then reference all the extra bits and pieces directly in the application project. The application project will tell me what it is missing when I try to run it. Things like the proxy factory (NHibernate.ByteCode.Castle, Castle.Core and Castle.DynamicProxy), secondary cache (NHibernate.Caches.SysCache), and HQL parsing (Antlr3.Runtime), etc. Just keep adding them as references in the application project after each complaint.
Edit
In the error you've posted it's complaining about not finding 'ByteCode.Castle'. The assembly in question is actually 'NHibernate.ByteCode.Castle'. The error may be in your App.config or Web.config where you've defined the proxy factory. Have you typed the assembly name correctly?
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
...
<property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
...
</session-factory>
</hibernate-configuration>

Okay here was the problem , in my code I was writing
ProxyFactoryFactory("ByteCode.Castle.ProxyFactoryFactory, ByteCode.Castle");
without the word nhibernate as i read nhibernate 2.1 removed that word from references so it was searching for bytecode.castle , and when i was renaming that dll it was making a missmatch and i was creating a big mess by myself ,now i just removed the name nhibernate and added references manually.....and it's working manually , thanks all :)

Related

Repository Pattern with Fluent Nhibernate

Hello everyone I've successfully implemented the repository pattern with fluentNHibernate but i have one concern abount the ExposeConfiguration when I removed it all the methods works fine but when i adds it ,it resets the tables in the database. so i need you to take a look and give me any notes about the implementation so here is my unit of work class
public class UnitOfWork
{
public static ISession NhibernateHelper()
{
ISessionFactory _sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString(#"Data Source=WAAIL-PC\COMPUTERENGINEER;Initial Catalog=TSQL2012;User ID=sa;Password=12345678Ce").ShowSql())
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<UsersMap>())
//.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(false, true)) //when i removed this line it doesn't
//remove the elements from the db
.BuildSessionFactory();
return _sessionFactory.OpenSession();
}}
and here is my repository pattern :
public class Repository<T> :IRepository<T> where T :BaseEntity
{
public Repository(/*IUnitOfWork unitOfWork*/)
{
//_unitOfWork = (UnitOfWork)unitOfWork;
}
public List<T> GetAll()
{
using (ISession Session = UnitOfWork.NhibernateHelper())
{
return Session.Query<T>().ToList();
}
}
public T GetById(int id)
{
using (ISession Session = UnitOfWork.NhibernateHelper())
{
return Session.Get<T>(id);
}
}
public T Insert(T entity)
{
try
{
using (ISession Session = UnitOfWork.NhibernateHelper())
{
using (ITransaction Transaction = Session.BeginTransaction())
{
Session.Save(entity);
Transaction.Commit();
}
}
return entity;
}
catch (Exception)
{
throw;
}
}
public void Update(T entity)
{
using (ISession Session = UnitOfWork.NhibernateHelper())
{
using (ITransaction Transaction = Session.BeginTransaction())
{
Session.Update(entity);
Transaction.Commit();
}
}
}
public void Delete(int id)
{
using (ISession Session = UnitOfWork.NhibernateHelper())
{
using (ITransaction Transaction = Session.BeginTransaction())
{
Session.Delete(Session.Load<T>(id));
Transaction.Commit();
}
}
}
}
here is my usersService
public class UsersService : IUsersService
{
private readonly IRepository<Users> _Repository;
#region Constructor
public UsersService(IRepository<Users> Repository)
{
_Repository = Repository;
}
#endregion
#region Service Implementation
public List<Users> GetListAll()
{
return _Repository.GetAll().ToList();
}
public Users GetById(int Id)
{
return _Repository.GetById(Id);
}
public Users Insert(Users user)
{
return _Repository.Insert(user);
}
public void Update(Users user)
{
_Repository.Update(user);
}
public void Delete(int Id)
{
_Repository.Delete(Id);
}
//public int execute()
//{
// return _Repository.execute();
//}
}
so what i need to know is why the Expose_configuration method causes the tables to reset... and secondly ,Am i moving in the right way in this implementation or not.
if you guys have any update of improvements please tell me ..
best regards.
The evil lies in details
You wrote:
... ExposeConfiguration when I removed it all the methods works fine but when i add it, it resets the tables in the database.
And that's pretty much normal way of operations, since if we look up NHiberate's SchemaExport classes Create method signature, it reads:
public void Create(Action<string> scriptAction, bool execute)
It's documentation states that Create():
Run the schema creation script
And about it parameters:
scriptAction - an action that will be called for each line of the generated ddl.
execute - if the ddl should be executed against the Database.
And you call it as:
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(false, true))
Your problem lies in that you pass true to the execute parameter, which will -as stated in documentation- execute the schema creation script, which might include drop and rerecration of existing database objects.
Why create demons?
About your second idea, I really see no benefit of adding another layer of indirection to your code, and that's where you summon unneeded demons.
The NHibernate ORM itself is an abstraction itself, why add one more generic one around it? Your Repository<T> just simply calls the already implemented generic NHibernate methods... sort of acting as Proxy to hide NHibernate, if that's intentional please pardon me, but it looks like it's not.
On a final note: your UsersService class first violates the Single responsibility principle and makes your life harder by maintaining and testing it. Second, this class is also not much more than a proxy to call the repository to return values from.
Let me illustrate the problem:
Client calls UsersService.GetById(Id)
Service calls _Repository.GetById(Id)
Your generic abstraction Repository calls NHibernates Session.Get<T>(id)
Do you see the problem?
How easier it would be to say use a pattern that might help you in this case, that is the Command Query Separation.
Where your commands are responsible for writes, and queries about reads and both suits your use-cases.
You can read about my answers earlier about queries and commands.

Nhibernate 2.1 with Spring on .net 4 throws System.ExecutionEngineException

I've got a website that works on .Net 3.5 running Nhibernate 2.1.0.4000. We are using spring as our ProxyFactory.
Everything works fine. I have tried to upgrade the project to .Net 4.0 using the wizard. It all went smoothly.
But as soon as the code tries to do anything with Nhibernate I get a very unfriendly exception of System.ExecutionEngineException. There is no stack trace and no inner exception.
We are using a NhibernateHelper class (below) and I've played around with it and the Session gets configured ok (no exception). The details havn't changed any from teh .net 3.5 version
The fist attempt to get something from the DB fails
The session is opened in the handler at the start of the request (not shown below).
We are also using unity which is setup on Appliation start (not sure if that has any bearing)
The First call to Nhibernate is
var emp = NHibernateHelper.CurrentSession.Get<SMS.DomainModel.Employee>(-200694);
I just want an error message that means something and gives me something to go on.
I've tried looking at NhibernateProfiler and all that is registered is the start of a session.
Any help is much appreciated
NhibernateHelper Class is as follows
using System;
using System.Configuration;
using System.IO;
using System.Reflection;
using FluentNHibernate;
using FluentNHibernate.Cfg;
using HibernatingRhinos.NHibernate.Profiler.Appender;
using log4net;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data.Configuration;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Event;
using NHibernate.Tool.hbm2ddl;
using SMS.Infrastructure.Persistence.Logging;
using SMS.Infrastructure.Persistence.Mappings;
using Configuration=NHibernate.Cfg.Configuration;
using System.Data.SqlClient;
namespace SMS.Infrastructure.Persistence
{
public static class NHibernateHelper
{
static readonly ILog Log = LogManager.GetLogger(typeof(NHibernateHelper));
static Configuration configuration;
public static ISessionFactory SessionFactory
{
get
{
return Singleton.sessionFactory;
}
}
// Lazy singleton pattern from http://www.yoda.arachsys.com/csharp/singleton.html
class Singleton
{
static Singleton() { }
internal static readonly ISessionFactory sessionFactory = CreateSessionFactory();
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
public static ISession CurrentSession
{
get { return SessionFactory.GetCurrentSession(); }
}
static ISessionFactory CreateSessionFactory()
{
try
{
Log.Info("Creating NHibernate session factory");
NHibernateProfiler.Initialize();
configuration = new Configuration();
try
{
// Try to configure NHibernate automagically...
configuration.Configure();
}
catch (HibernateConfigException e)
{
if (e.InnerException is IOException)
{
// Otherwise specify a file name manually.
configuration.Configure("hibernate.cfg.xml");
}
else
throw;
}
Log.Info("Registering custom SMS event listeners");
RegisterCustomListeners(configuration);
// Has someone specified a default_schema? No? try and guess
// it from the (Enterprise Library :/ ) query string.
if (!configuration.Properties.ContainsKey("default_schema"))
{
Log.Info("Setting default schema");
configuration.SetProperty("default_schema", GetDefaultSchema());
}
ISessionFactory sessionFactory = Fluently.Configure(configuration)
.Mappings(m =>
{
m.HbmMappings.AddFromAssemblyOf<BusinessUnitTypeMapping>();
m.FluentMappings.AddFromAssemblyOf<BusinessUnitTypeMapping>();
})
.BuildSessionFactory();
Log.Info("Session factory was configured successfully");
return sessionFactory;
}
catch (Exception ex)
{
throw new ArgumentNullException(ex.ToString());
}
}
/// <summary>
/// NHibernate allows custom event listeners to be registered in
/// config files or programmatically. Due to the re-use of configs in
/// SMS, we chose to do it via code.
///
/// This is how we extend NHibernate for SMS, and this is why
/// NHibernate is the best ORM..!
/// </summary>
static void RegisterCustomListeners(Configuration config)
{
if (config == null)
throw new ArgumentNullException("config");
// Event listeners for audit logging.
//config.SetListener(ListenerType.PreInsert, new AuditEventListener());
//config.SetListener(ListenerType.PreUpdate, new AuditEventListener());
//config.SetListener(ListenerType.PreDelete, new AuditEventListener());
// Event listener for wiring up .NET events between parent/child
// objects, and the intermediary mapping for Tasks.
//
// Warning: be careful with the order in which these listeners are
// added!!!
//
// BindEventsOnLoadListener must come before
// TaskAddresseeLoadEventListener for example otherwise OSM Task
// Decorators don't attach properly.
config.SetListeners(ListenerType.PostLoad, new IPostLoadEventListener[]
{
new BindEventsOnLoadListener(),
new TaskAddresseeLoadEventListener()
});
}
/// <summary>
/// Optional step: destroy and re-create the database scheme based on
/// the mapping files. Gives you a totally clean database in between
/// testing each fixture.
/// </summary>
public static void ExportDatabaseSchema(string fileName)
{
if (configuration == null)
CreateSessionFactory();
Log.InfoFormat("Exporting DDL to {0}", fileName);
var exporter = new SchemaExport(configuration);
exporter.SetOutputFile(fileName);
exporter.Execute(true, false, false);
}
public static void ExportFluentMappings(string directoryName)
{
Log.InfoFormat("Exporting fluent mappings to {0}", directoryName);
var model = new PersistenceModel();
model.AddMappingsFromAssembly(Assembly.GetAssembly(typeof(BusinessUnitTypeMapping)));
model.WriteMappingsTo(directoryName);
}
/// <summary>
/// hibernate's default_schema is worked out programmatically from the
/// Enterprise Library connection string. E.g.
/// Initial Catalog=OSM2Tests --> default_schema = SMS2Tests.dbo
/// </summary>
public static string GetDefaultSchema()
{
try
{
DatabaseSettings settings = DatabaseSettings.GetDatabaseSettings(new SystemConfigurationSource());
var connectionstring = ConfigurationManager.ConnectionStrings[settings.DefaultDatabase].ConnectionString;
var initialCatalog = new SqlConnectionStringBuilder(connectionstring).InitialCatalog;
return String.Format("{0}.dbo", initialCatalog);
}
catch (Exception)
{
throw new Exception("Could not get default schema from connection string.");
}
}
}
}
I was able to fix a similar problem by removing references to NHProf.

currentsessioncontext fluent nhibernate how to do it?

I am trying to use fluent with session per request. I am following a "recipe" from nhibernate cookbook however it uses the nhibernate config file.
I am not sure what is better but right now I am sticking with fluent config just because I would not know how to set the nhibernate config file to use fluent mapping and vanilla nhibernate mapping(hbm files).
namespace Demo.WebUI
{
public class MvcApplication : NinjectHttpApplication
{
public static ISessionFactory SessionFactory { get; private set; }
protected override void OnApplicationStarted()
{
SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(
c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings
.AddFromAssemblyOf
<Demo.Framework.Data.NhibernateMapping.UserMap>())
.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
var session = SessionFactory.OpenSession();
//CurrentSessionContext.Bind(session);
}
protected void Application_EndRequest(object sender, EventArgs e)
{
//var session = CurrentSessionContext.Unbind(SessionFactory);
SessionFactory.Dispose();
}
}
}
As you can see in the Begin_Request the books tutorial had
CurrentSessionContext.Bind(session);
However if I use this it throws a error since I don't have the nhibernate config file in use.
So how do I change it to use fluent configuration? Or do I not even need to do this step?(ie is it done internally?)
You need to tell NHibernate how to handle the session context. The following might work:
Fluently.Configure()
...
.ExposeConfiguration(cfg => cfg.SetProperty(
Environment.CurrentSessionContextClass,
"web")
Also, unrelated to this: you are disposing the SessionFactory on EndRequest. That is an error.
If your project is Asp.Net web site (not web application ), in Global.asax you should use like that
NHibernate.Cfg.Environment.CurrentSessionContextClass

Configuration which one should I be using? From fluent tutorial or from cookbook 3.0?

I am reading nhibernate cookbook 3.0 and the fluent tutorial and I am kinda confused which one I should be using(cookbook by itself has many different ways)
Fluent Nhibernate tutorial
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(
SQLiteConfiguration.Standard
.UsingFile("firstProject.db")
)
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<Program>())
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
private static void BuildSchema(Configuration config)
{
// delete the existing db on each run
if (File.Exists(DbFile))
File.Delete(DbFile);
// this NHibernate tool takes a configuration (with mapping info in)
// and exports a database schema from it
new SchemaExport(config)
.Create(false, true);
}
cookbook 3.0 pg(76) web request
1. In the hibernate-configuration section of web.config, add the current_
session_context_class property with a value of web.
2. If it doesn't exist already, add a new Global application class (Global.asax).
3. In Global.asax, add these using statements.
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Context;
4. Create a static property named SessionFactory.
public static ISessionFactory SessionFactory { get;
private set; }
5. In the Application_Start method, add the following code.
protected void Application_Start(object sender, EventArgs e)
{
log4net.Config.XmlConfigurator.Configure();
var nhConfig = new Configuration().Configure();
SessionFactory = nhConfig.BuildSessionFactory();
}
6. In the Application_BeginRequest method, add the following code.
protected void Application_BeginRequest(object sender, EventArgs e)
{
var session = SessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
}
7. In the Application_EndRequest method, add the following code:
protected void Application_EndRequest(object sender, EventArgs e)
{
var session = CurrentSessionContext.Unbind(SessionFactory);
session.Dispose();
}
Then they just use this to run it.
Guid productId = new Guid(Request["id"]);
Eg.Core.Product product;
var session = Global.SessionFactory.GetCurrentSession();
using (var tran = session.BeginTransaction())
{
product = session.Get<Eg.Core.Product>(productId);
tran.Commit();
}
Page.Title = product.Name;
Label1.Text = product.Name;
Label2.Text = product.Description;
With the fluent tutorial I am also kinda confused where I would typically put that code in an asp.net mvc application. I am trying to use the repository pattern with ninject(DI injection).
So with both ways I am not sure how to make it work with ninject and the repository pattern.
Is either way better for the repository pattern and Di?
Did you try to download the whole solution to run the project? These are just samples of code and you need the whole setup: VS project with Entity classes, mappings, repositories etc.
I would go to http://www.sharparchitecture.net/ and https://github.com/sharparchitecture download their Northwind sample project that has the exact setup that you need. You will have to find the Northwind database and install it on you local machine then modify the NHibernate.config to point to your database.

How can do I solve this? I want to inject a nhibernate session but the session is not created yet

Edit
I would like to try to do what Remo Gloor has recommended
Create a SessionFactoryProvider derived for Provider that retruns a SessionFactory using the code in OnApplicationStarted
Create a binding for SessionFactory using the new provider and put it in SingletonScope
Create a SessionProvider derived from Provider that gets the SessionFactory injected in the constructor and retuns a new session using GetCurrentSession of the factory.
Create a binding for ISession to the above provider with activation and deactivation actions that open, transmit, rollback, and close the session (basiclly the code from Application_BeginRequest, EndRequest). Decalre the binding as in request scope.
Remove Application_BeginRequest, EndRequest.
Bind the repo using Bind().To();
I am looking for a tutorial that hits on these points with a file that I can download and play around with. If it uses lots of generics you needs to be pretty detailed as generics still get me.
Hi
I am trying to do session per request with my nhibernate.
I done this in my global.aspx
using System;
using System.Web.Mvc;
using System.Web.Routing;
using Demo.WebUI.Models.NinjectModules;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Context;
using Ninject;
using Ninject.Modules;
using Ninject.Web.Mvc;
namespace Demo.WebUI
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Account", action = "Login", id = UrlParameter.Optional} // Parameter defaults
);
}
public static ISessionFactory SessionFactory { get; private set; }
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Demo.Framework.Data.NhibernateMapping.UserMap>())
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web"))
.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
ISession session = SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
}
protected void Application_EndRequest(object sender, EventArgs e)
{
ISession session = CurrentSessionContext.Unbind(SessionFactory);
if (session != null)
{
try
{
session.Transaction.Commit();
}
catch (Exception)
{
session.Transaction.Rollback();
}
finally
{
session.Close();
session.Dispose();
}
}
}
protected override IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new ServiceModule(),
new RepoModule()
};
return new StandardKernel(modules);
}
private static void BuidSchema(NHibernate.Cfg.Configuration config)
{
new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
}
}
}
In my RepoModule I have
Bind<IUserRepo>().To<UserRepo>().WithConstructorArgument("session",MvcApplication.SessionFactory.GetCurrentSession());
This will throw a error because ninject will create the kernal before OnApplicationStarted() gets started and before Application_Begin starts to bind it.
So what should I do?
Edit
This is what I found in some tutorial.
public static ISessionFactory SessionFactory { get; private set; }
public MvcApplication()
{
SessionFactory = CreateSessionFactory();
}
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Demo.Framework.Data.NhibernateMapping.UserMap>())
.ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web"))
.ExposeConfiguration(BuidSchema)
.BuildSessionFactory();
}
My binding
Bind<IUserRepo>().To<UserRepo>();
Bind<ISession>().ToMethod(x => MvcApplication.SessionFactory.GetCurrentSession());
So I first create the session factory on constructor load then I bind it to the Isession instead of passing it in as a parameter.
The only thing that I am not sure with the global aspx is if it will keep calling the constructor up everytime and recreating the SessionFactory what is bad. So I am not sure if I need to check if it exists first.
Your implementation is fine but not a good solution as you do manual control of the session lifecycle. The actual way this should be done is to let Ninject decide when the session is created, opened, closed and disposed.
E.g. imagine actions where you don't need any session. Or a larger project where you have several databases and sessions to split the load. In these situations you don't want all the possible sessions be created for each action as this means an avoidable overhead. You rather want that only those are created that are required for the current action.
To do so several changes are required:
Create a SessionFactoryProvider derived for Provider that retruns a SessionFactory using the code in OnApplicationStarted
Create a binding for SessionFactory using the new provider and put it in SingletonScope
Create a SessionProvider derived from Provider that gets the SessionFactory injected in the constructor and retuns a new session using GetCurrentSession of the factory.
Create a binding for ISession to the above provider with activation and deactivation actions that open, transmit, rollback, and close the session (basiclly the code from Application_BeginRequest, EndRequest). Decalre the binding as in request scope.
Remove Application_BeginRequest, EndRequest.
Bind the repo using Bind<IUserRepo>().To<UserRepo>();
I recently blogged about using nhibernate in an asp.net mvc application with a repository pattern. This project provides an example of using nhibernate & ninject. Here are a few links:
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/
I think that we have a similar architecture. Take a look at the posts and let me know if you have any questions.
BTW, you can download this project at http://gpsnerd.codeplex.com
Bob
Wrap the SessionFactory initialization code in a singleton, that will initialize and configure the sessionfactory once when you access the "Instance" property on it. Use this in BeginRequest instead of current code.
You're using a current session context, you don't have to inject the session!
Inject the SessionFactory instead, then use GetCurrentSession() to obtain an ISession.
After that change, you can use Felice's solution.