ServiceStack NHibernate Session для каждого запроса
Я начинаю создавать приложение и планирую использовать ServiceStack. Просто хочу узнать, каковы лучшие практики / подходы для работы с NHibernate ISession или другими объектами сеанса, специфичными для контекста "по запросу".
Я думал, что регистрация ISessionFactory в Ioc, например:
container.Register<ISessionFactory>(sessionFactory);
И когда нужно получить новый объект Session... Или, может быть, предоставить объект сеанса напрямую:
container.Register<ISession>(c => sessionFactory.OpenSession()).ReusedWithin(ReuseScope.None);
Или обработайте ISession и транзакцию по умолчанию через событие Global.asax BeginRequest:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var session = factory.OpenSession();
ITransaction itrans = session.BeginTransaction();
Context.Items.Add("session", session);
Context.Items.Add("trans", itrans);
}
Итак, я в некотором роде растерялся, каковы лучшие практики, учитывая вышеупомянутые технологии, или подобные, такие как EF или другая структура Rest-Services?
заранее спасибо
3 ответа
Смотрите этот пост в блоге для полного примера того, как оптимально использовать ServiceStack и NHibernate вместе:
http://www.philliphaydon.com/2012/06/using-nhibernate-with-servicestack/ Вот пример AppHost, использованный в приведенном выше посте:
public class Global : HttpApplication
{
public class SampleServiceAppHost : AppHostBase
{
private readonly IContainerAdapter _containerAdapter;
public SampleServiceAppHost(ISessionFactory sessionFactory)
: base("Service Stack with Fluent NHibernate Sample", typeof(ProductFindService).Assembly)
{
base.Container.Register<ISessionFactory>(sessionFactory);
}
public override void Configure(Funq.Container container)
{
container.Adapter = _containerAdapter;
}
}
void Application_Start(object sender, EventArgs e)
{
var factory = new SessionFactoryManager().CreateSessionFactory();
(new SampleServiceAppHost(factory)).Init();
}
}
Создание сеанса для каждого запроса с использованием HttpHandler - наиболее распространенный способ, который я нашел. Айенде объяснила, что создание сессии - это действительно легкий вес. http://ayende.com/blog/4123/what-is-the-cost-of-opening-a-session
У Ayende есть ряд постов, где он постепенно создает решение для доступа к данным. В каждом посте объясняется, почему он сделал то, что сделал, и какие проблемы необходимо решить с помощью шагов, предпринятых до сих пор. Начните здесь: http://ayende.com/blog/4803/refactoring-toward-frictionless-odorless-code-the-baseline
Все вышеперечисленное является вариацией сеанса на запрос. Общим для всех не является необходимость вручную беспокоиться о создании сеанса / транзакции. Они будут фиксировать / откатывать транзакции автоматически.
Я знаю, что это старый вопрос, но я решил показать всем, кто все еще заинтересован в альтернативном ответе, как мы это сделали.
Таким образом, мы используем ServiceRunner в новом API ServiceStack:
public class BaseServiceRunner<TRequest> : ServiceRunner<TRequest>
{
public BaseServiceRunner(AppHost appHost, ActionContext actionContext)
: base(appHost, actionContext) { }
public override void OnBeforeExecute(IRequestContext requestContext, TRequest request)
{
var req = request as MyRequestType;
if(req == null)
base.OnBeforeExecute(requestContext, request);
var factory = TryResolve<NHibernate.ISessionFactory>();
var session = factory.OpenSession();
var trans = session.BeginTransaction(IsolationLevel.ReadCommitted);
requestContext.SetItem("session", session);
requestContext.SetItem("transaction", trans);
}
public override object OnAfterExecute(IRequestContext requestContext, object response)
{
var trans = requestContext.GetItem("transaction") as ITransaction;
if (trans != null && trans.IsActive)
trans.Commit();
var session = requestContext.GetItem("session") as ISession;
if (session != null)
{
session.Flush();
session.Close();
}
return base.OnAfterExecute(requestContext, response);
}
public override object HandleException(IRequestContext requestContext, TRequest request, Exception ex)
{
var req = request as MyRequestType;
if(req != null)
{
var trans = requestContext.GetItem("transaction") as ITransaction;
if (trans != null && trans.IsActive)
trans.Rollback();
var session = requestContext.GetItem("session") as ISession;
if (session != null)
{
session.Flush();
session.Close();
}
}
return base.HandleException(requestContext, request, ex);
}
}