Reputation: 463
I'm having an issue trying to add a second db connection into the mix.
When I comment out the binding for the sybase db I don't get any errors. I've tried to put a conditional .WhenClassHas<CLASS>()
on the bindings to ISessionFactory
to no avail.
...
container.Bind<ISessionFactory>().ToProvider<MsSqlSessionFactoryProvider>().InSingletonScope().Named("mssql");
container.Bind<ISession>().ToProvider<MsSqlSessionProvider>().WhenClassHas<MsSqlNhibernateSessionAttribute>().InRequestScope();
container.Bind<ISessionFactory>().ToProvider<SybaseSessionFactoryProvider>().InSingletonScope().Named("sybase");
container.Bind<ISession>().ToProvider<SybaseSessionProvider>().WhenClassHas<NhibernateSessionAttribute>().InRequestScope();
container.Bind<ICurrentSessionContextAdapter>().To<CurrentSessionContextAdapter>();
...
public class MsSqlSessionFactoryProvider : Provider<ISessionFactory>
{
protected override ISessionFactory CreateInstance(IContext context)
{
return FluentNHibernate.Cfg.Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString(c => c.FromConnectionStringWithKey("MsSqlDbConnection")))
.CurrentSessionContext("web")
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<SqlCommandFactory>())
.BuildSessionFactory();
}
}
public class MsSqlSessionProvider : Provider<ISession>
{
protected override ISession CreateInstance(IContext context)
{
var sessionFactory = context.Kernel.Get<ISessionFactory>("mssql");
if (!CurrentSessionContext.HasBind(sessionFactory))
{
var session = sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
}
return sessionFactory.GetCurrentSession();
}
}
public class SybaseSessionFactoryProvider : Provider<ISessionFactory>
{
protected override ISessionFactory CreateInstance(IContext context)
{
return FluentNHibernate.Cfg.Fluently.Configure()
.Database(
OdbcConfiguration.Sybase.ConnectionString(c => c.FromConnectionStringWithKey("dbConnection")))
.ExposeConfiguration(c => c.SetProperty(NHibernate.Cfg.Environment.Hbm2ddlKeyWords, "none"))
.CurrentSessionContext("web")
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<OdbcCommandFactory>())
.BuildSessionFactory();
}
}
public class SybaseSessionProvider : Provider<ISession>
{
protected override ISession CreateInstance(IContext context)
{
var sessionFactory = context.Kernel.Get<ISessionFactory>("sybase");
if (!CurrentSessionContext.HasBind(sessionFactory))
{
var session = sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
}
return sessionFactory.GetCurrentSession();
}
}
using System.Web.Mvc;
namespace Common
{
public class MsSqlNhibernateSessionAttribute : ActionFilterAttribute/*, IActionFilter*/
{
private readonly IActionTransactionHelper _actionTransactionHelper;
private readonly IActionExceptionHandler _actionExceptionHandler;
public MsSqlNhibernateSessionAttribute()
: this(WebContainerManager.Get<IActionTransactionHelper>(),
WebContainerManager.Get<IActionExceptionHandler>())
{
}
public MsSqlNhibernateSessionAttribute(
IActionTransactionHelper actionTransactionHelper,
IActionExceptionHandler actionExceptionHandler)
{
_actionTransactionHelper = actionTransactionHelper;
_actionExceptionHandler = actionExceptionHandler;
}
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
_actionTransactionHelper.BeginTransaction();
}
public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
{
_actionTransactionHelper.EndTransaction(actionExecutedContext);
_actionTransactionHelper.CloseSession();
_actionExceptionHandler.HandleException(actionExecutedContext);
}
}
}
using System.Web.Mvc;
namespace Common
{
public class NhibernateSessionAttribute : ActionFilterAttribute
{
private readonly ISybaseActionTransactionHelper _sybaseActionTransactionHelper;
private readonly IActionExceptionHandler _actionExceptionHandler;
public NhibernateSessionAttribute()
: this(WebContainerManager.Get<ISybaseActionTransactionHelper>(),
WebContainerManager.Get<IActionExceptionHandler>())
{
}
public NhibernateSessionAttribute(
ISybaseActionTransactionHelper actionTransactionHelper,
IActionExceptionHandler actionExceptionHandler)
{
_sybaseActionTransactionHelper = actionTransactionHelper;
_actionExceptionHandler = actionExceptionHandler;
}
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
_sybaseActionTransactionHelper.BeginTransaction();
}
public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
{
_sybaseActionTransactionHelper.EndTransaction(actionExecutedContext);
_sybaseActionTransactionHelper.CloseSession();
_actionExceptionHandler.HandleException(actionExecutedContext);
}
}
}
I'm injecting it into the controller and have tried to inject it into the ActionTransactionHelper classes, but when I do that the error changes to "Error activating ISessionFactory. No matching bindings were found..." I'm including the controller and one ActionTransactionHelper as they are both the same implementation (I wasn't sure if I could have a single transaction helper class or not).
using System.Web.Mvc;
using Common;
using Data.SqlServer;
using NHibernate;
using Warehouse.Actions;
using Warehouse.Actions.VendorManagement;
namespace Warehouse.Controllers
{
[MsSqlNhibernateSession]
public class VendorManagementController : Controller
{
private readonly ISession _session;
public VendorManagementController(ISession session)
{
_session = session;
}
// GET: Vendor
public ActionResult Index()
{
ViewVendorManagementAction viewVendorManagementAction = new ViewVendorManagementAction();
return viewVendorManagementAction.Create(_session);
}
public ActionResult Vendor(Vendor vendor)
{
ViewVendorFormAction viewVendorFormAction = new ViewVendorFormAction();
return viewVendorFormAction.Create(Request, _session);
}
public ActionResult SaveVendor(Vendor vendor)
{
SaveVendorAction saveVendorAction = new SaveVendorAction(_session);
var newVendor = saveVendorAction.Save(vendor);
var returnUrl = Url.Action("Vendor") + "?Id=" + newVendor.Id;
return Redirect(returnUrl);
}
public ActionResult UpdateVendor(Vendor vendor)
{
UpdateVendorAction updateVendorAction = new UpdateVendorAction(_session);
updateVendorAction.Update(vendor);
var returnUrl = Url.Action("Vendor") + "?Id=" + vendor.Id;
return Redirect(returnUrl);
}
}
}
using System.Web.Mvc;
using NHibernate;
namespace Common
{
public class ActionTransactionHelper : IActionTransactionHelper
{
private readonly ISessionFactory _sessionFactory;
private readonly ICurrentSessionContextAdapter _currentSessionContextAdapter;
public ActionTransactionHelper(
ISessionFactory sessionFactory,
ICurrentSessionContextAdapter currentSessionContextAdapter)
{
_sessionFactory = sessionFactory;
_currentSessionContextAdapter = currentSessionContextAdapter;
}
public void BeginTransaction()
{
var session = _sessionFactory.GetCurrentSession();
if (session != null)
{
session.BeginTransaction();
}
}
public bool TransactionHandled { get; private set; }
public void EndTransaction(ActionExecutedContext filterContext)
{
var session = _sessionFactory.GetCurrentSession();
if (session == null) return;
if (!session.Transaction.IsActive) return;
if (filterContext.Exception == null)
{
session.Flush();
session.Transaction.Commit();
}
else
{
session.Transaction.Rollback();
}
TransactionHandled = true;
}
public bool SessionClosed { get; private set; }
public void CloseSession()
{
if (_currentSessionContextAdapter.HasBind(_sessionFactory))
{
var session = _sessionFactory.GetCurrentSession();
session.Close();
session.Dispose();
_currentSessionContextAdapter.Unbind(_sessionFactory);
SessionClosed = true;
}
}
}
}
Upvotes: 0
Views: 306
Reputation: 463
I figured out the solution to my issue. Thanks @BatteryBackupUnit for your help. It ended up being that I had to decorate my injection of ISessionFactory in the ActionTransactionHelper's with [Named("corresponding name from NinjectConfiguration binding to ISessionFactory")].
Ninject Documentation for contextual named bindings
Use .Named("name")
in the configuration file.
container.Bind<ISessionFactory>().ToProvider<MsSqlSessionFactoryProvider>().InSingletonScope().Named("mssql");
Then when injecting it get it by using [Named("name")]
public class ActionTransactionHelper : IActionTransactionHelper
{
private readonly ISessionFactory _sessionFactory;
private readonly ICurrentSessionContextAdapter _currentSessionContextAdapter;
public ActionTransactionHelper(
[Named("mssql")] ISessionFactory sessionFactory,
ICurrentSessionContextAdapter currentSessionContextAdapter)
{
_sessionFactory = sessionFactory;
_currentSessionContextAdapter = currentSessionContextAdapter;
}
}
Upvotes: 0
Reputation: 13233
The WhenClassHas<Attribute>
binding checks the class X where the bound type Y is injected into for an Attribute Z.
For example, when you have a binding
Bind<IFoo>().To<Foo>().WhenClassHas<MarkerAttribute>();
and:
[Marker]
public class Bar {
public Bar(IFoo foo) ...
}
this satifies the condition.
However, given:
public class ZZZ
{
public ZZZ(IFoo foo) ..
}
[Marker]
public class YYY {
public YYY(ZZZ zzz) ..
}
this does not satisfy the condition. IFoo
is injected into ZZZ
which does not have the [Marker]
attribute.
Also, when injecting into the [Marker]
attribute itself, this does not satisfy the condition as the [Marker]
attribute itself does not have the [Marker]
attribute on its class declaration.
Upvotes: 1