NHibernate 没有会话或会话被关闭
NHibernate no session or session was closed
错误
Initializing[Core.Model.Account#2586]-failed to lazily initialize a collection of role: Core.Model.Account.Roles, no session or session was closed
当我尝试使用 NHibernate 登录我的 Web 应用程序时出现。我不明白的是如何关闭连接,因为当我调试调用它的方法时,我可以打开使用的 NHibernate 会话的 isOpen
属性。
但是一旦延迟加载开始,显然 NHibernate 认为连接已关闭。怎么会这样?
我在 BeginRequest
中启动我的 NHibernate 会话并在 EndRequest
中关闭它们,这是推荐的。
Account.cs(在project/namespace/assemblyCore
)
public class Account
{
// ...
public virtual ISet<Role> Roles
{
get;
set;
}
// ...
public virtual bool HasPermission(Permission permission_)
{
foreach (Role role in Roles) {
if (role.Permissions.Contains(Permission.ALL) || role.Permissions.Contains(permission_)) {
return true;
}
}
return false;
}
}
Account.hbm.xml(在project/namespace/assemblyCore
)
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Core.Model.Account,Core" table="accounts">
<!-- ... -->
<set name="Roles" table="account_roles" lazy="true">
<key column="account"/>
<many-to-many class="Core.Model.Role" column="role" />
</set>
</class>
</hibernate-mapping>
Global.asax(在project/namespace/assemblyWeb
)
public AccountRepository Accounts;
private static ISessionFactory _sessionFactory;
private void Application_Start(object sender_, EventArgs e_)
{
_sessionFactory = new Configuration().Configure().BuildSessionFactory();
}
private void Application_BeginRequest(object sender_, EventArgs e_)
{
ISession session = _sessionFactory.OpenSession();
Accounts.SetSession(session);
HttpContext.Current.Items.Add("HibernateSession", session);
}
private void Application_EndRequest(object sender_, EventArgs e_)
{
ISession session = HttpContext.Current.Items["HibernateSession"] as ISession;
if (session != null && session.IsOpen) {
session.Close();
HttpContext.Current.Items.Remove("HibernateSession");
}
}
DecoratedSession.cs(在project/namespace/assemblyWeb
)
private static HttpSessionState _session
{
get
{
return HttpContext.Current.Session;
}
}
public static T Get<T>(string key_)
{
if (_session == null || _session[key_] == null) {
return default(T);
}
return (T)_session[key_];
}
public static void Set<T>(string key_, T value_)
{
_session[key_] = value_;
}
public static Account Account
{
get
{
return Get<Account>("Account");
}
set
{
Set<Account>("Account", value);
}
}
login.aspx(在project/namespace/assemblyWeb
)
protected void loginButton_Click(object sender, System.EventArgs e)
{
DecoratedSession.Account = Global.Firewall.Login(tb_user.Text, tb_user.Text);
Response.Redirect("main.aspx", true);
}
main.aspx(在project/namespace/assemblyWeb
)
protected void Page_Load(object sender, System.EventArgs e)
{
// Error thrown here, when accessing the "roles" set
if (DecoratedSession.Account.HasPermission(Permission.FULL_ACCESS))
{
// ...
}
}
我什至可以在日志文件中看到会话是打开的,然后发生异常,然后关闭。
Global: 15:20:08,669 DEBUG Global - Opened session [529000] for request to [/main.aspx]
Global: 15:20:08,670 DEBUG Global - STARTREQUEST Session id: [529000]
main: 15:20:08,682 DEBUG main - MAIN Session id: [529000]
NHibernate.LazyInitializationException: 15:20:08,685 ERROR NHibernate.LazyInitializationException - Initializing[Core.Model.Account#2586]-failed to lazily initialize a collection of role: Core.Model.Account.Roles, no session or session was closed
NHibernate.LazyInitializationException: Initializing[Core.Model.Account#2586]-failed to lazily initialize a collection of role: Core.Model.Account.Roles, no session or session was closed
Global: 15:20:14,160 DEBUG Global - Closed session [529000] for request to [/main.aspx]
我该如何调试它?
这里的重点是 (我没有深入研究上面的代码,但没有根据我的经验) 与 static vs http请求生命周期。
虽然有打开的会话,但导致其会话被关闭的对象来自之前的一些(与另一个网络请求相关)
在此处查看一些详细信息:
- Nhibernate Lazy Load exception after a view exception
我在介绍某种原型模式时看到的解决方案:
[Serializable]
public class Account, ICloneable, ...
{
...
public override object Clone()
{
var entity = base.Clone() as Account;
entity.Roles = ... (clone roles)
...
return entity;
}
...
并且在为身份验证加载帐户(用户、角色)时,我们应该调用 Clone()
以确保所有重要属性(多对一、一对一-to-many) 被加载,稍后可以使用。该克隆可以缓存在静态上下文中
错误
Initializing[Core.Model.Account#2586]-failed to lazily initialize a collection of role: Core.Model.Account.Roles, no session or session was closed
当我尝试使用 NHibernate 登录我的 Web 应用程序时出现。我不明白的是如何关闭连接,因为当我调试调用它的方法时,我可以打开使用的 NHibernate 会话的 isOpen
属性。
但是一旦延迟加载开始,显然 NHibernate 认为连接已关闭。怎么会这样?
我在 BeginRequest
中启动我的 NHibernate 会话并在 EndRequest
中关闭它们,这是推荐的。
Account.cs(在project/namespace/assemblyCore
)
public class Account
{
// ...
public virtual ISet<Role> Roles
{
get;
set;
}
// ...
public virtual bool HasPermission(Permission permission_)
{
foreach (Role role in Roles) {
if (role.Permissions.Contains(Permission.ALL) || role.Permissions.Contains(permission_)) {
return true;
}
}
return false;
}
}
Account.hbm.xml(在project/namespace/assemblyCore
)
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Core.Model.Account,Core" table="accounts">
<!-- ... -->
<set name="Roles" table="account_roles" lazy="true">
<key column="account"/>
<many-to-many class="Core.Model.Role" column="role" />
</set>
</class>
</hibernate-mapping>
Global.asax(在project/namespace/assemblyWeb
)
public AccountRepository Accounts;
private static ISessionFactory _sessionFactory;
private void Application_Start(object sender_, EventArgs e_)
{
_sessionFactory = new Configuration().Configure().BuildSessionFactory();
}
private void Application_BeginRequest(object sender_, EventArgs e_)
{
ISession session = _sessionFactory.OpenSession();
Accounts.SetSession(session);
HttpContext.Current.Items.Add("HibernateSession", session);
}
private void Application_EndRequest(object sender_, EventArgs e_)
{
ISession session = HttpContext.Current.Items["HibernateSession"] as ISession;
if (session != null && session.IsOpen) {
session.Close();
HttpContext.Current.Items.Remove("HibernateSession");
}
}
DecoratedSession.cs(在project/namespace/assemblyWeb
)
private static HttpSessionState _session
{
get
{
return HttpContext.Current.Session;
}
}
public static T Get<T>(string key_)
{
if (_session == null || _session[key_] == null) {
return default(T);
}
return (T)_session[key_];
}
public static void Set<T>(string key_, T value_)
{
_session[key_] = value_;
}
public static Account Account
{
get
{
return Get<Account>("Account");
}
set
{
Set<Account>("Account", value);
}
}
login.aspx(在project/namespace/assemblyWeb
)
protected void loginButton_Click(object sender, System.EventArgs e)
{
DecoratedSession.Account = Global.Firewall.Login(tb_user.Text, tb_user.Text);
Response.Redirect("main.aspx", true);
}
main.aspx(在project/namespace/assemblyWeb
)
protected void Page_Load(object sender, System.EventArgs e)
{
// Error thrown here, when accessing the "roles" set
if (DecoratedSession.Account.HasPermission(Permission.FULL_ACCESS))
{
// ...
}
}
我什至可以在日志文件中看到会话是打开的,然后发生异常,然后关闭。
Global: 15:20:08,669 DEBUG Global - Opened session [529000] for request to [/main.aspx]
Global: 15:20:08,670 DEBUG Global - STARTREQUEST Session id: [529000]
main: 15:20:08,682 DEBUG main - MAIN Session id: [529000]
NHibernate.LazyInitializationException: 15:20:08,685 ERROR NHibernate.LazyInitializationException - Initializing[Core.Model.Account#2586]-failed to lazily initialize a collection of role: Core.Model.Account.Roles, no session or session was closed
NHibernate.LazyInitializationException: Initializing[Core.Model.Account#2586]-failed to lazily initialize a collection of role: Core.Model.Account.Roles, no session or session was closed
Global: 15:20:14,160 DEBUG Global - Closed session [529000] for request to [/main.aspx]
我该如何调试它?
这里的重点是 (我没有深入研究上面的代码,但没有根据我的经验) 与 static vs http请求生命周期。
虽然有打开的会话,但导致其会话被关闭的对象来自之前的一些(与另一个网络请求相关)
在此处查看一些详细信息:
- Nhibernate Lazy Load exception after a view exception
我在介绍某种原型模式时看到的解决方案:
[Serializable]
public class Account, ICloneable, ...
{
...
public override object Clone()
{
var entity = base.Clone() as Account;
entity.Roles = ... (clone roles)
...
return entity;
}
...
并且在为身份验证加载帐户(用户、角色)时,我们应该调用 Clone()
以确保所有重要属性(多对一、一对一-to-many) 被加载,稍后可以使用。该克隆可以缓存在静态上下文中