gpt4 book ai didi

NHibernate 多线程问题

转载 作者:行者123 更新时间:2023-12-04 02:35:21 25 4
gpt4 key购买 nike

我有一个 ASP.NET MVC 应用程序,我想为它编写一些压力测试,以了解来自多个线程的并发数据库访问。我使用 Parallel.ForEach() 将其编写为单元测试,但无法使其工作,因为我大部分时间都遇到以下异常:

There is already an open DataReader associated with this Command which must be closed first

所以我尽可能地简化了测试,这里是
[Test]
public void Can_Access_DB_Concurrently()
{
Parallel.ForEach(Enumerable.Range(0, 9), x =>
{
try
{
var sessionBuilder = new HybridSessionBuilder();
var session = sessionBuilder.GetSession();

using (ITransaction transaction = session.BeginTransaction())
{
var job = session.Query<Job>().Where(y => y.Name == "TestProject").SingleOrDefault().Name;
Trace.WriteLine(Thread.CurrentThread.ManagedThreadId + ": Job name is " + job);
transaction.Commit();
}
}
catch (Exception e)
{
Trace.WriteLine(Thread.CurrentThread.ManagedThreadId + ": Exception: " + e.Message);
}
});
}

典型输出:
13: Exception: Object reference not set to an instance of an object.
16: Exception: There is already an open DataReader associated with this Command which must be closed first.
9: Exception: There is already an open DataReader associated with this Command which must be closed first.
16: Exception: There is already an open DataReader associated with this Command which must be closed first.
14: Exception: There is already an open DataReader associated with this Command which must be closed first.
HybridSessionBuilder看起来像这样:
public class HybridSessionBuilder : ISessionBuilder
{
private static ISessionFactory _sessionFactory;
private static ISession _currentSession;

public ISession GetSession()
{
ISessionFactory factory = getSessionFactory();
ISession session = getExistingOrNewSession(factory);
return session;
}

private ISessionFactory getSessionFactory()
{
lock (this)
{
if (_sessionFactory == null)
{
Configuration configuration = GetConfiguration();
_sessionFactory = configuration.BuildSessionFactory();
}

return _sessionFactory;
}
}

public Configuration GetConfiguration()
{
string connectionString = WebConfigurationManager.ConnectionStrings["StagingDatabase"].ConnectionString;

Configuration configuration = new Configuration();
configuration = PostgreSQLConfiguration.PostgreSQL82
.ConnectionString(connectionString)
.Dialect("NHibernate.Dialect.PostgreSQL82Dialect")
.UseReflectionOptimizer()
.AdoNetBatchSize(50)
.ConfigureProperties(new Configuration());

configuration.AddMappingsFromAssembly(typeof(Job).Assembly);
Fluently.Configure(configuration);
return configuration;
}

private ISession getExistingOrNewSession(ISessionFactory factory)
{
{
if (HttpContext.Current != null)
{
ISession session = GetExistingWebSession();
if (session == null)
{
session = openSessionAndAddToContext(factory);
}
else if (!session.IsOpen)
{
session = openSessionAndAddToContext(factory);
}

return session;
}

if (_currentSession == null)
{
_currentSession = factory.OpenSession();
}
else if (!_currentSession.IsOpen)
{
_currentSession = factory.OpenSession();
}
}

return _currentSession;
}

public ISession GetExistingWebSession()
{
return HttpContext.Current.Items[GetType().FullName] as ISession;
}

private ISession openSessionAndAddToContext(ISessionFactory factory)
{
ISession session = factory.OpenSession();
HttpContext.Current.Items.Remove(GetType().FullName);
HttpContext.Current.Items.Add(GetType().FullName, session);
return session;
}
}

显然我在这个并发访问上做错了,但我无法发现错误。谢谢你的任何建议。

最佳答案

HybridSessionBuilder将 ISession 存储在静态成员中,因此为每个线程重用它。修复测试的最简单解决方案是删除 static关键字来自 _currentSession . HybridSessionBuilder的每个实例然后将提供不同的 ISession .

关于NHibernate 多线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7886260/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com