Как настроить NHibernate с Sharp Architecture в многопоточном консольном приложении?
Я все еще довольно новичок в этих технологиях. Настоящая проблема здесь заключается в том, как управлять сеансами для потока в консольном приложении. В настоящее время, если я запускаю его как единый поток, все хорошо. Как только я переключаюсь на многопоточную модель, я начинаю видеть конфликт на уровне сеанса (поскольку объект Session не является безопасным по своей конструкции). Возникают исключения KeyNotFound (среди прочих).
В веб-приложении вы бы сделали что-то вроде этого:
/// <summary>
/// Due to issues on IIS7, the NHibernate initialization cannot reside in Init() but
/// must only be called once. Consequently, we invoke a thread-safe singleton class to
/// ensure it's only initialized once.
/// </summary>
protected void Application_BeginRequest(object sender, EventArgs e)
{
NHibernateInitializer.Instance().InitializeNHibernateOnce(
() => InitializeNHibernateSession());
}
/// <summary>
/// If you need to communicate to multiple databases, you'd add a line to this method to
/// initialize the other database as well.
/// </summary>
private void InitializeNHibernateSession()
{
var path = ConfigurationManager.AppSettings["NHibernateConfig"];
NHibernateSession.Init(
webSessionStorage,
new string[] { Server.MapPath("~/bin/foo.Data.dll") },
new AutoPersistenceModelGenerator().Generate(),
Server.MapPath("~/App_Configuration/" + path ));
}
// sample of my console app... very simple
static void Main(string[] args)
{
InitializeNHibernateSession();
while(true)
{
Task.Factory.StartNew(() => SomeAwesomeLongRunningPieceOfWork());
}
}
Который по существу выполняет инициализацию один раз для потока (веб-запроса) в global.asax.
Любые идеи о том, как настроить это (управление сеансом) в консольном приложении?
1 ответ
Это сработало для меня:
// Three threads:
for (int i = 0; i < 3; i++)
{
Thread curThread = new Thread(StartThread);
curThread.Start();
}
private void StartThread()
{
NHibernateInitializer.Instance().InitializeNHibernateOnce(InitializeNHibernateSession);
SomeAwesomeLongRunningPieceOfWork();
}
private void InitializeNHibernateSession()
{
var path = ConfigurationManager.AppSettings["NHibernateConfig"];
NHibernateSession.Init(
new ThreadSessionStorage(),
new string[] { "foo.Data.dll" },
new AutoPersistenceModelGenerator().Generate(),
"./App_Configuration/" + path);
}
Ключ был этот класс, который я получил от:
http://groups.google.com/group/sharp-architecture/browse_thread/thread/ce3d9c34bc2da629?fwc=1 http://groups.google.com/group/sharp-architecture/browse_thread/thread/51794671c91bc5e9/386efc30d4c0bf16
public class ThreadSessionStorage : ISessionStorage
{
[ThreadStatic]
private static ISession _session;
public ISession Session
{
get
{
return _session;
}
set
{
_session = value;
}
}
public ISession GetSessionForKey(string factoryKey)
{
return Session;
}
public void SetSessionForKey(string factoryKey, ISession session)
{
Session = session;
}
public IEnumerable<ISession> GetAllSessions()
{
return new List<ISession>() { Session };
}
}
И это работает просто отлично.