Fluent NHibernate中的内存泄漏
本文关键字:内存 泄漏 NHibernate Fluent | 更新日期: 2023-09-27 18:03:11
我正在使用Fluent NHibernate作为我们的ORM,我正在获得内存泄漏错误。
我在任务管理器中观察到,每当我试图在同一台PC上从不同的web浏览器访问主页时,CPU使用率为2-3%,但内存使用率为80-90%,导致网站变慢并导致系统挂起。要再次运行我的网站,我必须从任务管理器结束进程。还有一件事,当我从浏览器访问它时,它使用一些内存,但当我关闭它时,它不会释放所有的资源(内存)。
我以这种方式制作了我的网站架构:-
- 我已经做了一个类"ParentObject",我已经创建了存储库对象作为静态成员。
- 我创建的所有实体都继承自"ParentObject"类。
-
我已经做了一个类BaseController,我已经从"控制器"类继承和在基类我已经使用了这个代码:-
protected override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); EdustructRepository Repository; // My Repository Class where I have written logic for opening and closing Save and Update Session.I have mentioned my this logic below if (Session["Repository"] != null) { Repository = (EdustructRepository)Session["Repository"]; if (!Repository.GetSession().Transaction.IsActive) Repository.GetSession().Clear(); } else { Repository = new EdustructRepository(typeof(ActivityType), FluentNhibernateRepository.DataBaseTypes.MySql); Session["Repository"] = Repository; } if (ParentObject._repository == null) { ParentObject._repository = new EdustructRepository(); // Here i have set the ParentObject's static variable "_repository" by this i have accessed repository in all my Entities . } }
-
我已经继承了我所有的控制器与BaseController类。这样我就得到了"_repository"对象,每个Action都命中。
My session management Logic
public class EdustructRepository : NHibernetRepository
{
public void Save<T>(T item, bool clearSession)
{
if (typeof(T).GetProperty("Created_at").GetValue(item, null).ToString() == DateTime.MinValue.ToString())
{
typeof(T).GetProperty("Created_at").SetValue(item, MySqlDateTime.CurrentDateTime(), null);
}
typeof(T).GetProperty("Updated_at").SetValue(item, MySqlDateTime.CurrentDateTime(), null);
base.CheckAndOpenSession();
using (var transaction = base.GetSession().BeginTransaction())
{
try
{
base.GetSession().SaveOrUpdate(item);
transaction.Commit();
if (clearSession)
{
Session.Clear();
}
}
catch
{
base.Evict(item);
base.Clear();
throw;
}
}
//base.Save<T>(item, clearSession);
}
public void Save<T>(T item)
{
Save<T>(item, false);
}
}
public class NHibernetRepository : IDisposable
{
public static ISessionFactory _SessionFactory = null;
protected ISession Session = null;
private ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MySQLConfiguration.Standard.ConnectionString(c => c.FromConnectionStringWithKey("DBConnectionString")))
.Mappings(m =>m.FluentMappings.AddFromAssembly((Assembly.Load("Edustruct.Social.DataModel"))).Conventions.Add<CascadeConvention>())
.ExposeConfiguration(cfg => cfg.SetProperty(NHibernate.Cfg.Environment.CurrentSessionContextClass,"web"))
.BuildSessionFactory();
}
protected void CheckAndOpenSession()
{
if (_SessionFactory == null)
{
_SessionFactory = CreateSessionFactory();
}
if (Session == null)
{
Session = _SessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
}
if (!Session.IsOpen)
Session = _SessionFactory.OpenSession();
else if (!Session.IsConnected)
Session.Reconnect();
}
}
注意:我们没有在我们的存储库中关闭会话,这是因为我正在使用惰性初始化,我也在视图中使用它,所以如果我在这里关闭会话,我会得到一个错误显示"未找到会话"。
这就是我如何使我的网站流量。请检查这个代码,让我知道为什么我得到这个错误。
提前感谢您
问题:
- 你基本上保持一个会话每个实体永远打开。然而,issession实现的工作单元模式并不是为了这个。
-
CheckAndOpenSession()
不是线程安全的,但web服务本质上是线程的:每个请求通常都有自己的线程。
每个业务操作都应该有自己的会话,并在会话结束时被处理。业务操作通常是一个控制器动作或web方法。
示例// on appstart
GlobalSessionFactory = CreateSessionFactory();
// in basecontroller befor action
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
DatabaseSession = GlobalSessionFactory.OpenSession();
}
// in basecontroller after action (pseudocode)
protected override void OnActionExecuted()
{
DatabaseSession.Dispose();
}