NHibernate温莎每个请求的实现
本文关键字:请求 实现 NHibernate | 更新日期: 2023-09-27 18:11:34
我在我的项目中使用了NHibernate和Castle Windsor Injection。我的NHibernate实现是这样的:
Component.For<ISessionFactory>().UsingFactoryMethod(CreateSessionFactory).LifestyleSingleton(),
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>().LifestyleSingleton(),
Component.For<ISession>().UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession()).LifestylePerWebRequest(),
如果我想双击刷新页面或在新选项卡上打开某些页面,我会得到错误
ExecuteReader需要一个打开且可用的连接。连接的当前状态是关闭的。
我的实现有什么错误吗?怎么了?怎么解呢?
这是UnitOfWork类:公共单位工作电流{得到{If (_current == null)_current = new UnitOfWork(sessionFactory, Session);返回_current;}}(ThreadStatic)private UnitOfWork _current
/// <summary>
/// Gets Nhibernate session object to perform queries.
/// </summary>
public ISession Session { get; get; }
/// <summary>
/// Reference to the session factory.
/// </summary>
private readonly ISessionFactory sessionFactory;
/// <summary>
/// Reference to the currently running transcation.
/// </summary>
private ITransaction transaction;
/// <summary>
/// Creates a new instance of NhUnitOfWork.
/// </summary>
/// <param name="sessionFactory"></param>
public UnitOfWork(ISessionFactory _sessionFactory, ISession _session)
{
sessionFactory = _sessionFactory;
Session = _session;
}
/// <summary>
/// Opens database connection and begins transaction.
/// </summary>
public void BeginTransaction(IsolationLevel isoLevel=IsolationLevel.ReadCommitted)
{
transaction = Session.BeginTransaction(isoLevel);
}
/// <summary>
/// Commits transaction and closes database connection.
/// </summary>
public void Commit()
{
transaction.Commit();
}
/// <summary>
/// Rollbacks transaction and closes database connection.
/// </summary>
public void Rollback()
{
transaction.Rollback();
}
public void Dispose()
{
//Session.Dispose();
}
如果您在web项目中这样做,并且您的PerWebRequest windsor Lifestyle建议,我会摆脱您的工作实现单元,并直接处理来自global .asax的请求事件。在web中,工作单元是请求。我还喜欢使用安装程序来连接Windsor。这是一个适合我的配置。
public class MvcApplication : HttpApplication
{
private const String Sessionkey = "current.session";
private static IWindsorContainer Container { get; set; }
private static ISessionFactory SessionFactory { get; set; }
public static ISession CurrentSession
{
get { return (ISession) HttpContext.Current.Items[Sessionkey]; }
private set { HttpContext.Current.Items[Sessionkey] = value; }
}
protected void Application_Start()
{
Version version = Assembly.GetExecutingAssembly().GetName().Version;
Application["Version"] = String.Format("{0}.{1}", version.Major, version.Minor);
Application["Name"] = ConfigurationManager.AppSettings["ApplicationName"];
//create empty container
//scan this assembly for any installers to register services/components with Windsor
Container = new WindsorContainer().Install(FromAssembly.This());
//API controllers use the dependency resolver and need to be initialized differently than the mvc controllers
GlobalConfiguration.Configuration.DependencyResolver = new WindsorDependencyResolver(Container.Kernel);
//tell ASP.NET to get its controllers from Castle
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container.Kernel));
//initialize NHibernate
ConnectionStringSettings connectionString = ConfigurationManager.ConnectionStrings[Environment.MachineName];
if (connectionString == null)
throw new ConfigurationErrorsException(String.Format("Connection string {0} is empty.",
Environment.MachineName));
if (String.IsNullOrWhiteSpace(connectionString.ConnectionString))
throw new ConfigurationErrorsException(String.Format("Connection string {0} is empty.",
Environment.MachineName));
string mappingAssemblyName = ConfigurationManager.AppSettings["NHibernate.Mapping.Assembly"];
if (String.IsNullOrWhiteSpace(mappingAssemblyName))
throw new ConfigurationErrorsException(
"NHibernate.Mapping.Assembly key not set in application config file.");
var nh = new NHInit(connectionString.ConnectionString, mappingAssemblyName);
nh.Initialize();
SessionFactory = nh.SessionFactory;
AutoMapConfig.RegisterMaps();
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ModelBinderConfig.RegisterModelBinders(ModelBinders.Binders);
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
}
protected void Application_OnEnd()
{
//dispose Castle container and all the stuff it contains
Container.Dispose();
}
protected void Application_BeginRequest() { CurrentSession = SessionFactory.OpenSession(); }
protected void Application_EndRequest()
{
if (CurrentSession != null)
CurrentSession.Dispose();
}
}}
这是我的NhInit类
public class NHInit : NHibernateInitializer
{
public NHInit(String connectionString, String mappingAssemblyName) : base(connectionString, mappingAssemblyName)
{
}
}
NHibernateInitializer
public abstract class NHibernateInitializer : IDomainMapper
{
protected Configuration Configure;
private ISessionFactory _sessionFactory;
private readonly ModelMapper _mapper = new ModelMapper();
private Assembly _mappingAssembly;
private readonly String _mappingAssemblyName;
private readonly String _connectionString;
protected NHibernateInitializer(String connectionString, String mappingAssemblyName)
{
if (String.IsNullOrWhiteSpace(connectionString))
throw new ArgumentNullException("connectionString", "connectionString is empty.");
if (String.IsNullOrWhiteSpace(mappingAssemblyName))
throw new ArgumentNullException("mappingAssemblyName", "mappingAssemblyName is empty.");
_mappingAssemblyName = mappingAssemblyName;
_connectionString = connectionString;
}
public ISessionFactory SessionFactory
{
get
{
return _sessionFactory ?? (_sessionFactory = Configure.BuildSessionFactory());
}
}
private Assembly MappingAssembly
{
get
{
return _mappingAssembly ?? (_mappingAssembly = Assembly.Load(_mappingAssemblyName));
}
}
public void Initialize()
{
Configure = new Configuration();
Configure.EventListeners.PreInsertEventListeners = new IPreInsertEventListener[] { new EventListener() };
Configure.EventListeners.PreUpdateEventListeners = new IPreUpdateEventListener[] { new EventListener() };
Configure.SessionFactoryName(System.Configuration.ConfigurationManager.AppSettings["SessionFactoryName"]);
Configure.DataBaseIntegration(db =>
{
db.Dialect<MsSql2008Dialect>();
db.Driver<SqlClientDriver>();
db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
db.IsolationLevel = IsolationLevel.ReadCommitted;
db.ConnectionString = _connectionString;
db.BatchSize = 20;
db.Timeout = 10;
db.HqlToSqlSubstitutions = "true 1, false 0, yes 'Y', no 'N'";
});
Configure.SessionFactory().GenerateStatistics();
Map();
}
public virtual void InitializeAudit()
{
var enversConf = new Envers.Configuration.Fluent.FluentConfiguration();
enversConf.Audit(GetDomainEntities());
Configure.IntegrateWithEnvers(enversConf);
}
public void CreateSchema()
{
new SchemaExport(Configure).Create(false, true);
}
public void DropSchema()
{
new SchemaExport(Configure).Drop(false, true);
}
private void Map()
{
_mapper.AddMappings(MappingAssembly.GetExportedTypes());
Configure.AddDeserializedMapping(_mapper.CompileMappingForAllExplicitlyAddedEntities(), "MyWholeDomain");
}
public HbmMapping HbmMapping
{
get { return _mapper.CompileMappingFor(MappingAssembly.GetExportedTypes()); }
}
public IList<HbmMapping> HbmMappings
{
get { return _mapper.CompileMappingForEach(MappingAssembly.GetExportedTypes()).ToList(); }
}
/// <summary>
/// Gets the domain entities.
/// </summary>
/// <returns></returns>
/// <remarks>by default anything that derives from EntityBase and isn't abstract or generic</remarks>
protected virtual IEnumerable<System.Type> GetDomainEntities()
{
List<System.Type> domainEntities = (from t in MappingAssembly.GetExportedTypes()
where typeof(EntityBase<Guid>).IsAssignableFrom(t)
&& (!t.IsGenericType || !t.IsAbstract)
select t
).ToList();
return domainEntities;
}
}
SessionInstaller
public class SessionInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container
.Register(Component.For<ISession>().UsingFactoryMethod(() => MvcApplication.CurrentSession)
.LifeStyle
.PerWebRequest);
}
}
ControllersInstaller
public class ControllersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<IController>()
.LifestyleTransient());
}
}
控制器工厂public class WindsorControllerFactory : DefaultControllerFactory
{
// Fields
private readonly IKernel _kernel;
// Methods
public WindsorControllerFactory(IKernel kernel)
{
if (kernel == null)
throw new ArgumentNullException("kernel");
_kernel = kernel;
}
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType == null)
throw new HttpException(0x194,
string.Format(
"The controller for path '{0}' could not be found or it does not implement IController.",
context.HttpContext.Request.Path));
return (IController) _kernel.Resolve(controllerType);
}
}