Skip to content

Instantly share code, notes, and snippets.

@dealproc
Last active August 29, 2015 14:07
Show Gist options
  • Save dealproc/8036162b4c566de2308b to your computer and use it in GitHub Desktop.
Save dealproc/8036162b4c566de2308b to your computer and use it in GitHub Desktop.
NHibernateSessionSource
using NHibernate;
using NLog;
public class AccountAccessor : IAccountAccessor {
Logger Log = LogManager.GetCurrentClassLogger();
ISessionFactory _SessionFactory;
public AccountAccessor(ISessionFactory sessionFactory) {
_SessionFactory = sessionFactory;
}
public Account GetCurrentAccount() {
using (var session = _SessionFactory.OpenSession()) {
var _AccountRepository = new AccountRepository(new UnitOfWork(session));
string hostname = System.Web.HttpContext.Current.Request.Url.Host;
Log.Debug("Host name resolved from HttpContext.Current == {0}", hostname);
if (string.IsNullOrWhiteSpace(hostname)) {
throw new UnknownAccountException(1, "Could not resolve hostname from HttpContext.Current.");
}
var account = _AccountRepository.GetFirst(x => x.Hostname == hostname);
if (account == null) {
Log.Debug("Account was not found in system.");
throw new UnknownAccountException(2, string.Format("Hostname: {0} has not been registered.", hostname));
}
Log.Debug("Associated Account Id/GUID: {0}/{1}", account.Id, account.GUID);
return account;
}
}
}
public class ClaimsPrincipalAccountAccessor : IAccountAccessor {
Logger Log = LogManager.GetCurrentClassLogger();
ISessionFactory _SessionFactory;
public ClaimsPrincipalAccountAccessor(ISessionFactory sessionFactory) {
_SessionFactory = sessionFactory;
}
public Core.DataModel.Users.Account GetCurrentAccount() {
using (var session = _SessionFactory.OpenSession()) {
var _AccountRepository = new AccountRepository(new UnitOfWork(session));
var principal = HttpContext.Current.User as ClaimsPrincipal;
if (principal == null) {
throw new SecurityException("User is unauthorized.");
}
try {
var accountClaim = principal.Claims.First(x => x.Type == Constants.ClaimTypes.TenantId);
var account = _AccountRepository.GetFirst(x => x.GUID == accountClaim.Value);
if (account == null) {
Log.Debug("Account was not found in the system.");
throw new UnknownAccountException(3, "Account cannot be found from hardware's claims.");
};
Log.Debug("Associated Account Id/GUID: {0}/{1}", account.Id, account.GUID);
return account;
} catch (Exception) {
Log.Debug("User is not a hardware device. Throwing 'null' back to calling method.");
return null;
}
}
}
}
public interface IAccountAccessor {
Account GetCurrentAccount();
}
public interface ISessionSource {
ISession CreateSession();
}
using Autofac;
using System;
public class NHibernateMultitenantConfigModule : Module {
protected override void Load(ContainerBuilder builder) {
if (builder == null) {
throw new ArgumentNullException("builder");
}
builder.Register<Account>(x => {
return x.Resolve<IAccountAccessor>().GetCurrentAccount();
});
builder.RegisterType<NHibernateSessionSource>()
.AsImplementedInterfaces()
.SingleInstance();
builder.Register(c => {
var threadContext = c.Resolve<IComponentContext>();
return new UnitOfWork(threadContext.Resolve<ISessionSource>().CreateSession());
})
.AsSelf()
.InstancePerRequest();
}
}
using Autofac.Features.OwnedInstances;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Caches.SysCache;
using NHibernate.Dialect;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using Configuration = NHibernate.Cfg.Configuration;
public class NHibernateSessionSource : ISessionSource {
Dictionary<Account, ISessionFactory> _SessionFactories = new Dictionary<Account, ISessionFactory>();
static readonly object _FactorySyncRoot = new object();
string _ConnectionStringModel = "";
Owned<IAccountAccessor> _AccountAccessor;
public NHibernateSessionSource(Owned<IAccountAccessor> accountAccessor) {
_AccountAccessor = accountAccessor;
_ConnectionStringModel = ConfigurationManager.ConnectionStrings["ClientDBTemplate"].ConnectionString;
}
public NHibernate.ISession CreateSession() {
var account = _AccountAccessor.Value.GetCurrentAccount();
return GetSessionFactory(account).OpenSession();
}
private Configuration BuildConfiguration(Account account) {
var rawConfig = new NHibernate.Cfg.Configuration();
rawConfig.SetNamingStrategy(new PostgresqlNamingStrategy());
var configuration = Fluently.Configure(rawConfig)
.Database(
PostgreSQLConfiguration.Standard
.Driver<ProfiledNpgsqlDriver>()
.Dialect<PostgreSQL82Dialect>()
.ConnectionString(
string.Format(_ConnectionStringModel, account.DatabaseName)
)
)
.ExposeConfiguration(c => c.SetProperty(NHibernate.Cfg.Environment.ReleaseConnections, "on_close"))
.ExposeConfiguration(c => c.SetProperty(NHibernate.Cfg.Environment.ShowSql, "false"))
.ExposeConfiguration(c => c.SetProperty(NHibernate.Cfg.Environment.UseSecondLevelCache, "true"))
.Cache(c => c.ProviderClass<SysCacheProvider>().UseQueryCache().UseSecondLevelCache())
.Mappings(m => {
m.AutoMappings.Add(
AutoMap
.AssemblyOf<NHibernateConfigModule>(new AutomappingConfiguration())
.UseOverridesFromAssemblyOf<Infrastructure.Mappings.ItemMapOverride>()
.Conventions.AddFromAssemblyOf<DateTimeOffsetValueConverter>()
.Conventions.AddFromAssemblyOf<Infrastructure.Conventions.HasManyToManyConvention>()
.IncludeBase<Core.DataModel.Transactions.TransactionPayment>()
);
})
.BuildConfiguration();
return configuration;
}
private ISessionFactory BuildSessionFactory(Configuration config) {
var sessionFactory = config.BuildSessionFactory();
if (sessionFactory == null) {
throw new Exception("Cannot build NHibernate Session Factory");
}
return sessionFactory;
}
private ISessionFactory GetSessionFactory(Account account) {
var accountSessionFactory = _SessionFactories.Where(kvp => kvp.Key.GUID == account.GUID).Select(x => x.Value).SingleOrDefault();
if (accountSessionFactory == null) {
lock (_FactorySyncRoot) {
var cfg = BuildConfiguration(account);
accountSessionFactory = cfg.BuildSessionFactory();
_SessionFactories.Add(account, accountSessionFactory);
}
}
return accountSessionFactory;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment