c# - NHibernate 没有 session 或 session 已关闭

标签 c# session nhibernate

错误

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 session 的 isOpen 属性。

但是一旦延迟加载开始,显然 NHibernate 就认为连接已关闭。怎么会发生这种事?

按照建议,我在 BeginRequest 中启动 NHibernate session ,并在 EndRequest 中关闭它们。

Account.cs(在项目/命名空间/程序集 Core 中)

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(在项目/命名空间/程序集Core中)

<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(在项目/命名空间/程序集 Web 中)

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");
    }
}

DecolatedSession.cs(在项目/命名空间/程序集 Web 中)

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(在项目/命名空间/程序集 Web 中)

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);
}

ma​​in.aspx(在项目/命名空间/程序集 Web 中)

protected void Page_Load(object sender, System.EventArgs e)
{
    // Error thrown here, when accessing the "roles" set
    if (DecoratedSession.Account.HasPermission(Permission.FULL_ACCESS))
    {
        // ...
    }
}

我什至可以在日志文件中看到 session 是开放的,然后发生异常,然后关闭。

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]

如何调试这个?

最佳答案

这里的要点是与静态http请求相关的(我没有深入研究上面的代码,而是基于我的经验)生命周期。

虽然存在打开的 session ,但其 session 被关闭的对象归咎于之前的一些(与另一个网络请求相关)

在此处查看一些详细信息:

我在引入某种原型(prototype)模式时看到的解决方案:

[Serializable]
public class Account, ICloneable, ...
{
    ...
    public override object Clone()
    {
        var entity = base.Clone() as Account;
        entity.Roles = ... (clone roles)
        ...
        return entity;
    }
    ...

在加载帐户(用户、角色)进行身份验证时,我们应该调用 Clone() 以确保所有重要属性(多对一、一对一) -to-many)已加载并可供稍后使用。该克隆可以缓存在静态上下文中

关于c# - NHibernate 没有 session 或 session 已关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33148317/

相关文章:

c# - REST Api 服务器挂起大量请求(使用 c# HttpClient)

c# - 如何精确测量字符的宽度?

php - 从另一个 php 文件访问 SESSION 变量

c# - 如何为作为唯一列集的多值组件创建 NHibernate 映射文件?

c# - 同类的 Fluent/NHibernate Collections

NHibernate 一对多 - 为什么它用空外键更新子项?

c# - ASP.NET Core Web API - 如何在中间件管道中隐藏 DbContext 事务?

c# - 从字符串中检索货币符号

java - hibernate "The resource type Session does not implement java.lang.AutoCloseable"

javascript - Microsoft Edge 扩展 document.cookie 存储失败