现在,我的会话工厂生活在我的控制器中,并且一次又一次地被创建。如何创建一个在控制器之间共享的?
public class AccountsController : Controller
{
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MySQLConfiguration.Standard.ConnectionString(
c => c.FromConnectionStringWithKey("DashboardModels")
))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Accounts>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Notes>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Sales_Forecast>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<ChangeLog>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Tasks>())
.BuildSessionFactory();
}
ISessionFactory sessionFactory = CreateSessionFactory();
...
...
编辑我已经添加了SessionController类,如下所示:
public class SessionController : Controller
{
public HttpSessionStateBase HttpSession
{
get { return base.Session; }
}
public new ISession Session { get; set; }
}
并创建了一个新的SessionFactory实用程序类
public class NHibernateActionFilter : ActionFilterAttribute
{
private static readonly ISessionFactory sessionFactory = BuildSessionFactory();
private static ISessionFactory BuildSessionFactory()
{
return new Configuration()
.Configure()
.BuildSessionFactory();
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var sessionController = filterContext.Controller as SessionController;
if (sessionController == null)
return;
sessionController.Session = sessionFactory.OpenSession();
sessionController.Session.BeginTransaction();
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var sessionController = filterContext.Controller as SessionController;
if (sessionController == null)
return;
using (var session = sessionController.Session)
{
if (session == null)
return;
if (!session.Transaction.IsActive)
return;
if (filterContext.Exception != null)
session.Transaction.Rollback();
else
session.Transaction.Commit();
}
}
}
问题/疑虑:使用FluentNhibernate,我应该如何配置我的新SessionFactory类,以及如何在我的控制器中创建和使用事务?
答案 0 :(得分:1)
您需要使SessionFactory静态,以便所有控制器都使用相同的实例。 Ayende有good blog post作为如何做到这一点的例子,以及如何在交易中包装动作。
public class SessionController : Controller
{
public HttpSessionStateBase HttpSession { get { return base.Session; } }
public new ISession Session { get; set; }
}
//you could put this class in the same physical file as the SessionController.cs
//since they are tightly coupled to each other
public class NHibernateActionFilter : ActionFilterAttribute
....
然后将您的AccountController更改为...
public class AccountsController : SessionController
{
public ActionResult Index()
{
//Session is primed and ready for use
}
}
最后确保在global.asax
中注册动作过滤器答案 1 :(得分:0)
这就是我个人解决问题的方法(在DotJoe和其他网站的帮助下)
<强>的Global.asax.cs 强>
public static ISessionFactory SessionFactory =
SessionProvider.BuildSessionFactory();
protected void Application_Start()
{
SessionFactory.OpenSession();
}
<强>控制器强>
public ActionResult ReadAccounts([DataSourceRequest] DataSourceRequest request)
{
DataSourceResult result;
using(ISession session = TRX.CRM.Dashboard.Web.UI.MvcApplication.SessionFactory.OpenSession())
{
using (ITransaction tx = session.BeginTransaction())
{
var customers = session.Query<Accounts>().Where(a => a.Deleted == false).AsNoTracking();
//from customer in session.Query<Accounts>().AsNoTracking()
// where !customer.Deleted
// select customer;
result = customers.ToDataSourceResult(request);
tx.Commit();
}
}
return Json(result, JsonRequestBehavior.AllowGet);
}
然后我在名为Utilities的文件夹中创建了一个类:
<强> SessionFactory.cs 强>
public class SessionProvider
{
public static ISessionFactory BuildSessionFactory()
{
return Fluently.Configure()
.Database(MySQLConfiguration.Standard.ConnectionString(
c => c.FromConnectionStringWithKey("DashboardModels")
))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Accounts>())
.BuildSessionFactory();
}
}
我希望这段代码可以帮助其他需要从EF转换为NHibernate的人。
这使我的内存管理保持在一个非常大的应用程序中,有145个用户,超过450,000kb。 (使用EF从600,000kb下降)证明了NHibernate的可扩展性。
NHProf也是强烈推荐的。它有很好的建议,并将为您的具体问题提供资源。
如果您打算使用Mono,我认为这是一种方式。