Asp.net mvc NHibernate/MVC延迟加载失败;会议结束或无会议“;

Asp.net mvc NHibernate/MVC延迟加载失败;会议结束或无会议“;,asp.net-mvc,nhibernate,Asp.net Mvc,Nhibernate,我在ASP.NETMVC应用程序后面使用NHibernate,在尝试通过AJAX调用保存对象时遇到了一个令人沮丧的问题。我得到了通常的: 未能延迟初始化角色集合:[type]未关闭任何会话或会话 问题是,据我所知,会议还没有结束。我正在使用一个HttpModule来处理每个请求会话模式下的会话,NHibernate设置为使用webcurrent\u session\u context\u类。以下是HttpModule: public class NHHttpModule : IHttpModul

我在ASP.NETMVC应用程序后面使用NHibernate,在尝试通过AJAX调用保存对象时遇到了一个令人沮丧的问题。我得到了通常的:

未能延迟初始化角色集合:[type]未关闭任何会话或会话

问题是,据我所知,会议还没有结束。我正在使用一个HttpModule来处理每个请求会话模式下的会话,NHibernate设置为使用webcurrent\u session\u context\u类。以下是HttpModule:

public class NHHttpModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.EndRequest += ApplicationEndRequest;
        context.BeginRequest += ApplicationBeginRequest;
    }

    public void ApplicationBeginRequest(object sender, EventArgs e)
    {
        CurrentSessionContext.Bind(SessionFactory.GetNewSession());
    }

    public void ApplicationEndRequest(object sender, EventArgs e)
    {
        var currentSession = CurrentSessionContext.Unbind(SessionFactory.GetSessionFactory());
        currentSession.Close();
        currentSession.Dispose();
    }

    public void Dispose()
    {
        // Do nothing
    }
}
我的SessionFactory也很标准:

public static class SessionFactory
{
    private static ISessionFactory _sessionFactory;

    private static void Init()
    {
        _sessionFactory = Fluently.Configure() //Lots of other stuff here for NH config
            .BuildSessionFactory();
    }

    public static ISessionFactory GetSessionFactory()
    {
        if (_sessionFactory == null)
            Init();

        return _sessionFactory;
    }

    public static ISession GetNewSession()
    {
        return GetSessionFactory().OpenSession();
    }

    public static ISession GetCurrentSession()
    {
        return GetSessionFactory().GetCurrentSession();
    }
}
我在事务中使用一个工作单元,这就是为什么我不在BeginRequest中打开事务。即使如此,我也尝试过,结果没有改变

我正试图通过AJAX帖子将
注释
对象保存到
用户
对象。以下是控制器代码:

    [HttpPost, ValidateInput(false)]
    public ActionResult CreateCommentAsync(CommentCreateViewModel model)
    {
        if (!model.UserId.HasValue)
            return Content("false");

        var svc = DependencyResolver.Current.GetService<IPartnerUserService>();
        var user = svc.FindBy(model.UserId.Value, UserContext.Current.ActiveUser);

        // I put this in here as a test -- it throws the no-session error, too.            
        var count = user.Comments.Count();

        var comment = new Comment();
        comment.CommentText = model.CommentText;
        comment.DateCreated = DateTime.UtcNow;
        comment.CreatedBy = UserContext.Current.ActiveUser;

        // This is the original source of the error
        user.Comments.Add(comment);
        svc.Save(user, UserContext.Current.ActiveUser);

        return Content("true");
    }
我在条件下得到
true
的结果

评论者请求服务上的代码,但对于该特定调用,它不涉及会话,它只是验证请求用户是否具有权限,然后设置分离的条件。然后在该服务中调用存储库,代码如下:

public IEnumerable<T> FindBy(DetachedCriteria detachedCriteria) //Infrastructure.Querying.Query query)
{
    return detachedCriteria.GetExecutableCriteria(SessionFactory.GetCurrentSession()).Future<T>();
}
public IEnumerable FindBy(DetachedCriteria DetachedCriteria)//Infrastructure.Query.Query查询)
{
返回detachedCriteria.GetExecutableCriteria(SessionFactory.GetCurrentSession()).Future();
}
我认为这段代码不是问题的原因是,它与为details视图调用的代码完全相同。当我显示注释时,我没有任何延迟加载错误,我也是这样做的——我使用服务加载用户对象,然后在列表中执行
foreach
迭代。我做那件事从来没有遇到过困难

如果这是AJAX调用的某种问题,我也将其更改为完整回发,但仍然得到相同的错误


我一辈子都搞不清楚这里发生了什么。

可能是集合映射有问题。您确定映射正确且实体已正确绑定吗

选中一对多和多对一和反向属性

已更新

您是否尝试将“用户”实体附加到session.Lock(..)中


我可以建议您尝试保存单个用户实体或单个注释实体,以测试问题是否来自注释收集。

当您要对视图中的会话执行某些操作时,也会引发此异常。

检查一下这个

我终于找到了这个错误的原因,但只是运气不好。我会发布决议,以防它对某人有所帮助,但我无法真正解释原因,可能会发布一个新问题,看看是否有人可以澄清问题

您会注意到,在我的代码中,我是这样调用我的服务的:

if (!SessionFactory.GetCurrentSession().Contains(user))
    SessionFactory.GetCurrentSession().Refresh(user);
var user = svc.FindBy(model.UserId.Value, UserContext.Current.ActiveUser);
UserContext
对象是一个静态类,其会话存储在
Current
实例中,该实例包含一个属性,该属性是当前用户记录NHibernate对象。由于NHibernate如何代理属性,因此无论何时调用该
UserContext.ActiveUser
属性,都必须执行类似的操作:

if (!SessionFactory.GetCurrentSession().Contains(ActiveUser))
    SessionFactory.GetCurrentSession().Refresh(ActiveUser);
出于某种原因,正是这个刷新过程把事情搞砸了。当我显式地检索活动用户而不是使用
UserContext
类时,一切正常


此后,我更改了检索活动用户的方式,使其不使用会话存储实例,并且工作正常。我希望我知道确切的原因,但我不知道

是的,我确信映射是正确的。我不仅可以访问详细信息视图中的注释列表,还可以间歇添加注释而不出错。我很确定这是一个会话问题。问题是我的用户对象是在MVC应用程序中创建的,因此对会话没有直接的了解。我没有为注释设置存储库,因为它不是聚合根。在更改实体的关联方式之前,我想看看是否可以修复会话管理,但作为最后手段,我会记住这一点。因此,注释不会作为用户集合映射到存储库中?这就是问题所在吗?它们被映射,并且可以1)间歇性地保存在web应用程序中,2)始终保存在控制台应用程序中,当前会话上下文类设置为
call
。这不是映射,而是会话管理,我几乎是肯定的。请发布“svc.FindBy(model.UserId.Value,UserContext.Current.ActiveUser);”实际做的事情。内在逻辑。如果用户是根据以前的请求从另一个会话中选择的,则会出现此错误。添加了相关代码。我询问的方法包含2个参数,您发布的方法包含1个DetachedCriteria。您可能有IPartnerUserService的特定服务,该服务具有另一个方法签名。你粘贴了泛型的。我注意到方法名上有异步。您是否使用普通控制器而不是异步控制器对此进行了测试?您是否有可能在另一个线程上运行并偶尔关闭或处理会话的内容?哦,我现在明白您的意思了,但是您返回了一个IPersonUser,我想知道它是如何工作的。还有,什么是CurrentSessionContext?Bind是做什么的?谢谢,这是我检查过的线程之一。我的问题不同——延迟加载在同一上下文中失败。因此,我不会加载实体并处理会话,然后尝试获取延迟加载的属性。当调试显示会话仍然处于活动状态时,我正在加载并立即尝试延迟加载。也许您应该尝试获取所有注释以创建代理,例如session.createcriteria();在尝试添加新模型之前?如果是这样,那么我就失去了NH丰富域模型的所有好处。我宁愿找到核心问题,也不愿实施变通办法。很抱歉,我没有其他解决办法