шаблон рекомендаций для использования для обработки сеансов для веб-запросов в MVC с использованием NHibernate
-
12-12-2019 - |
Вопрос
Например.Моя фабрика сеансов находится в классе MyDomain.SessionProvider.Сессия может быть открытой using ISession session = SessionProvider.Instance.OpenSession()
Шаг:Сеанспровидер.cs
public static SessionProvider Instance { get; private set; }
private static ISessionFactory _SessionFactory;
static SessionProvider()
{
var provider = new SessionProvider();
provider.Initialize();
Instance = provider;
}
private SessionProvider()
{
}
private void Initialize()
{
string csStringName = "ConnectionString";
var cfg = Fluently.Configure()
//ommiting mapping and db conf.
.ExposeConfiguration(c => c.SetProperty("current_session_context_class", "web"))
.BuildConfiguration();
_SessionFactory = cfg.BuildSessionFactory();
}
public ISession OpenSession()
{
return _SessionFactory.OpenSession();
}
public ISession GetCurrentSession()
{
return _SessionFactory.GetCurrentSession();
}
Шаг:Global.asax.cs
public static ISessionFactory SessionFactory { get; private set; }
Запуск приложения
SessionFactory = SessionProvider.Instance.OpenSession().SessionFactory;
App_BeginRequest
var session = SessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
Endrequest расположить сеанс
var session = CurrentSessionContext.Unbind(SessionFactory);
session.Dispose();
Шаг 3. HomeControllerЯ должен использовать текущий сеанс, например
var session = SessionProvider.Instance.GetCurrentSession();
using (var tran = session.BeginTransaction())
{
//retrieve data from session
}
Теперь, пытаясь получить данные на моем контроллере, например desc.в Шаге3.Я получил сообщение об ошибке, что мой сеанс закрыт.Я попытался удалить блок Application_EndRequest внутри global.asax, потому что моя транзакция была обернута сеансом, но безуспешно.Все та же ошибка.
Второй/побочный вопрос:широко ли принят этот шаблон, или его лучше обернуть внутри пользовательских атрибутов контроллеров MVC.Спасибо.
Обновлено:На моем контроллере при попытке создать текущий сеанс в строке
var session = SessionProvider.Instance.GetCurrentSession();
Я получаю следующую ошибку:
**Connection = 'session.Connection' threw an exception of type 'NHibernate.HibernateException'**
**base {System.ApplicationException} = {"Session is closed"}**
Решение
Спасибо @LeftyX
Я решил эту проблему с помощью видео TekPub Mastering NHibernate с некоторыми настройками.
Global.asax
//Whenever the request from page comes in (single request for a page)
//open session and on request end close the session.
public static ISessionFactory SessionFactory =
MyDomain.SessionProvider.CreateSessionFactory();
public MvcApplication()
{
this.BeginRequest += new EventHandler(MvcApplication_BeginRequest);
this.EndRequest +=new EventHandler(MvcApplication_EndRequest);
}
private void MvcApplication_EndRequest(object sender, EventArgs e)
{
CurrentSessionContext.Unbind(SessionFactory).Dispose();
}
private void MvcApplication_BeginRequest(object sender, EventArgs e)
{
CurrentSessionContext.Bind(SessionFactory.OpenSession());
}
protected void Application_Start()
{
SessionFactory.OpenSession();
}
и внутри моего контроллера
var session = MvcApplication.SessionFactory.GetCurrentSession();
{
using (ITransaction tx = session.BeginTransaction())
{... omitting retrieving data}
}
Другие советы
Вы можете найти пару простых и легких реализаций. здесь и здесь и найди какой-нибудь код здесь.
Мне нравится подход Ayende: все просто и понятно:
public class Global: System.Web.HttpApplication
{
public static ISessionFactory SessionFactory = CreateSessionFactory();
protected static ISessionFactory CreateSessionFactory()
{
return new Configuration()
.Configure(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "hibernate.cfg.xml"))
.BuildSessionFactory();
}
public static ISession CurrentSession
{
get{ return (ISession)HttpContext.Current.Items["current.session"]; }
set { HttpContext.Current.Items["current.session"] = value; }
}
protected void Global()
{
BeginRequest += delegate
{
CurrentSession = SessionFactory.OpenSession();
};
EndRequest += delegate
{
if(CurrentSession != null)
CurrentSession.Dispose();
};
}
}
В своих проектах я решил использовать IoC-контейнер (StructureMap).
Если вам интересно, вы можете посмотреть здесь.