0

I have a web app that uses the iBATIS.NET library.

The DAO is configured by using an XmlDocument, so the code is very similar to what they show in the documentation:

XmlDocument anXmlDoc = someSupportClass.GetDynamicXmlDocument();
DomDaoManagerBuilder builder = new DomDaoManagerBuilder();
builder.Configure(anXmlDoc);

The documentation says right below that:

The DaoManager instance that is built from a dao.config file is aware of all of the contexts contained within the configuration file. The context basically bundles DAO implementations together with a session handler. The DaoManager knows which DAOs and session handler belong to which context. When you request a DAO instance from the DaoManager, the proper session handler will be provided with it. Therefore, there is no need to access the context or session handler directly. Your DAO knows how it works.

This does not appear to be true. In a threaded process, the following exception is thrown randomly:

WebSessionStore: Could not obtain reference to HttpContext at IBatisNet.DataAccess.SessionStore.WebSessionStore.ObtainSessionContext() at IBatisNet.DataAccess.SessionStore.WebSessionStore.get_LocalSession()
at IBatisNet.DataAccess.DaoManager.IsDaoSessionStarted() at IBatisNet.DataAccess.Configuration.DaoProxy.Intercept(IInvocation invocation, Object[] arguments)

The application may run fine for days or even months at a time, but every once in awhile this exception is thrown. The only solution I can find mentioned anywhere is to swap out the SessionStore for a HybridWebThreadSessionStore (mentioned here).

As the documentation says above, this shouldn't be necessary. If I wanted to force it though, how would I go about overriding the SessionStore created by the DomDaoManagerBuilder?

4

2 回答 2

1

该问题似乎是由应用程序启动时 iBatis.NET 框架中的竞争条件引起的。如果在单独线程上调用数据库之前在主线程上调用数据库,那么单独的线程将引发错误,因为它们没有 HttpContext 存储在 SessionStore 中。

基本上去了Startup -> db call on main thread -> db call on separate thread

应该是什么时候Startup -> db call on separate thread -> db call on main thread

基本上,我只是更改了事件触发的顺序,以确保在主线程上的任何事情发生之前至少调用线程上的 db 调用一次。

这篇文章描述了同样的问题

设置

在我的 Global.asax 中,我使用 Timer 类启动了一个后台进程。此 Timer 类使用定期调用的 delgate DoTimerBasedStuff()。DoTimerBasedStuff() 方法访问两个不同的数据库,MySQL 和 SQL Server。两者都使用它们的 MySQLMapper 和 SQLServerMapper 类正确设置。

除了这些后台线程之外,该应用程序还有一个 Web 前端,它使用典型的 .aspx 页面和从 Page 继承的类来访问这两个数据库。没有什么花哨。

问题

如果应用程序是通过使用浏览器转到 index.aspx 来启动的(此页面不执行任何 db 操作,但会触发 Global.asax)并且在第一次调用 DoTimerBasedStuff() 之前没有采取其他操作,一切都很好,并且后台进程和网络用户都很好。IBatis 做的一切都是正确的。

但是,如果我通过转到 index.aspx 来启动应用程序,然后立即通过访问数据库的 Web 进行一些工作(在执行 DoTimerBasedStuff() 之前),则 DoTimerBasedStuff() 方法无法访问 HttpContext 并给出以下错误:

例外:WebSessionStore:无法在 IBatisNet.DataMapper.SessionStore.WebSessionStore.get_LocalSession() 在 IBatisNet.DataMapper.SqlMapper.QueryForObject(String ...

于 2014-12-31T18:29:08.163 回答
0

发生错误是因为您在不同的线程中运行 ibatis。您可以在查询数据库之前使用 HybridWebThreadSessionStore 的新实例。

var map = new Hashtable
{
   { "FilterA", "MyFilter" }
};
SqlMap.SessionStore = new HybridWebThreadSessionStore(SqlMap.Id);
var listadoJobs = SqlMap.QueryForList<EventoJob>(SbsIbatisConstantes.ListarJobs, map).ToList();

您可以在此处查看此参考

这对我有用。

于 2019-04-26T00:21:12.883 回答