我从 nHibernate 开始,并希望从第一天开始就这样做,所以这就是我使用 ISession 的方式。(每个请求的网络)
这是我的帮手:
using System;
using System.Data;
using System.Web;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Context;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Mapping.ByCode;
using NHibernate.Tool.hbm2ddl;
namespace Gigastence.nHibernate.Web
{
public static class Helper
{
#region Public Enums
public enum DatabaseType
{
MSSQL2005,
MSSQL2008,
MySQL,
MySQL5
}
#endregion
#region Private Members
private static HbmMapping _hbmMapping;
private static Type[] _mappingTypes;
private static Configuration _nHibernateConfiguration;
#endregion
#region Public Properties
public static bool GenerateStatistics { get; set; }
public static string ConnectionString { get; set; }
public static ISession GetCurrentSession
{
get
{
// Store the current ISession
ISession tempSession = GetSessionFactory.GetCurrentSession();
// Return the current Session in for the relevant Context
return tempSession.IsOpen ? tempSession : OpenSession();
}
}
public static ISessionFactory GetSessionFactory { get; private set; }
public static DatabaseType WorkingDatabaseType { get; set; }
#endregion
#region Private Methods
private static void CompileSessionFactory()
{
// ToDo: See if we can speed up this process by creating a static file to reference
//
// Build the nHibernate Configuration and store it
_nHibernateConfiguration = ConfigureNHibernate();
// Deserialize and Add the supplied Mappings to the nHibernate Configuration
_nHibernateConfiguration.AddDeserializedMapping(_hbmMapping, null);
// ToDo: Figure out what this does!
//
SchemaMetadataUpdater.QuoteTableAndColumns(_nHibernateConfiguration);
// Create the Session Factory and store it
GetSessionFactory = _nHibernateConfiguration.BuildSessionFactory();
}
private static Configuration ConfigureNHibernate()
{
// Create a new nHibernate configuration
var configure = new Configuration();
// ToDo: Allow for setting name of SessionFactory
//
// Name the Session Factory
configure.SessionFactoryName("Default");
// Wire up Session Factory Database component based on working database type
switch (WorkingDatabaseType)
{
case DatabaseType.MySQL5:
// !!! Is a MySQL 5 Database
configure.DataBaseIntegration(db =>
{
db.Dialect<MySQL5Dialect>();
db.Driver<MySqlDataDriver>();
db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
db.IsolationLevel = IsolationLevel.ReadCommitted;
db.ConnectionString = ConnectionString;
db.Timeout = 10;
});
break;
}
// Generate Statistics, if required
if (GenerateStatistics) configure.SessionFactory().GenerateStatistics();
// ToDo: Add modifier based on required Session Context
//
configure.CurrentSessionContext<ManagedWebSessionContext>();
// Return the Configuration
return configure;
}
#endregion
#region Public Methods
public static void AddMapping(Type mappingType)
{
// Determine if array is already available
if (_mappingTypes == null)
{
// Create a new array with one element
_mappingTypes = new Type[1];
}
// Copy existing array into a new array with one more element
Array.Resize(ref _mappingTypes, _mappingTypes.Length + 1);
// Add the Mapping Type
Array.Copy(new object[] { mappingType }, 0, _mappingTypes, _mappingTypes.Length - 1, 1);
}
public static void AddMappings(Type[] mappingTypes)
{
// Iterate through passed types
foreach(Type passedType in mappingTypes)
{
// Add each typre
AddMapping(passedType);
}
}
public static void Application_BeginRequest()
{
// Add the ISession object to the current request's Context for use throughout the request
ManagedWebSessionContext.Bind(HttpContext.Current, OpenSession());
}
public static void Application_End()
{
// Dispose of the Session Factory
GetSessionFactory.Dispose();
}
public static void Application_EndRequest()
{
// Unbind the Session from the request's context and place in the ISession holder
ISession session = ManagedWebSessionContext.Unbind(HttpContext.Current, GetSessionFactory);
// Flush and Close the Session if it is still open
if (session == null || !session.IsOpen) return;
// Proceed
session.Flush();
session.Close();
session.Dispose();
}
public static void Application_Error()
{
// Rollback transaction if there is one
RollbackTransaction();
}
public static void BuildDatabase()
{
// ToDo: Tidy Up and extend
new SchemaExport(_nHibernateConfiguration).Execute(false, true, false);
}
public static void BuildSessionFactory(bool forceRebuild)
{
// Determine if this is a forced rebuild
if (forceRebuild)
{
// !!! Forced rebuild
// Compile Session Factory
CompileSessionFactory();
}
else
{
// !!! Not a forced rebuild
// Reference the current Session Factory if available
ISessionFactory sessionFactory = GetSessionFactory;
// Determine if Session Factory is built already
if (sessionFactory == null)
{
// Compile Session Factory
CompileSessionFactory();
}
}
}
public static void CompileMappings(Type baseEntityToIgnore)
{
// Using the built-in auto-mapper
var mapper = new ModelMapper();
// Add prefetched Types to Mapper
mapper.AddMappings(_mappingTypes);
// Compile the retrieved Types into the required Mapping
_hbmMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
}
public static ISession OpenSession()
{
return GetSessionFactory.OpenSession();
}
public static void RollbackTransaction()
{
// Get the current ISession from the request's context and place in the ISession holder
ISession session = GetCurrentSession;
// Determine if the ISession exists
if (session == null) return;
// It does, rollback current transaction if there is one
if (session.Transaction.IsActive && !session.Transaction.WasRolledBack)
{
// There was a transaction, rollback
session.Transaction.Rollback();
}
}
#endregion
}
}
这就是我使用它的方式:
using (ISession session = Helper.GetCurrentSession)
{
using (ITransaction transaction = session.BeginTransaction())
{
// Add data to the NHibernateSchemaVersions table
var table = new NHibernateSchemaVersions { Component = "Web.Provider.Membership", Version = 1 };
session.Save(table);
transaction.Commit();
}
}
到目前为止,我知道这是我应该做的,将工作包装在事务中。
不过,由于 ISession 对象上的 USING 语句,我发现会话在每次调用结束时关闭;这就是为什么我在 Helper.GetCurrentSession 调用中添加了检查它是否仍然打开的逻辑。
我这样做对吗?我认为会话旨在保持活动状态直到请求结束,并确定它何时进入数据库。
我是否应该简单地获取会话并使用它而不是 USING 语句:
ISession session = Helper.GetCurrentSession;
using (ITransaction transaction = session.BeginTransaction())
{
// Add data to the NHibernateSchemaVersions table
var table = new NHibernateSchemaVersions { Component = "Web.Provider.Membership", Version = 1 };
session.Save(table);
transaction.Commit();
}
如果是这种情况,我会在其他地方遇到问题吗?
感谢您的时间和帮助。
注意:我确实在寻找答案,但我无法将我的问题与任何事情联系起来。如果我错过了,请给我一个链接。