Nhibernate 为什么在使用Autofac时我的会话不会自动刷新? 概述

Nhibernate 为什么在使用Autofac时我的会话不会自动刷新? 概述,nhibernate,asp.net-mvc-4,autofac,Nhibernate,Asp.net Mvc 4,Autofac,我正在尝试连接Autofac,以帮助在我的MVC4RC项目中管理NHibernate的ISession。据我所知,Autofac应该按照我配置的方式在每个HTTP请求结束时调用ISession.Dispose(见下文)。然而,情况似乎并非如此——如果我不调用ISession.Flush(),数据就不会持久化到数据库中 配置 自动传真 container.Register(c=>DbConfig.Generate(connectionString.BuildSessionFactory()) .A

我正在尝试连接Autofac,以帮助在我的MVC4RC项目中管理NHibernate的
ISession
。据我所知,Autofac应该按照我配置的方式在每个HTTP请求结束时调用
ISession.Dispose
(见下文)。然而,情况似乎并非如此——如果我不调用
ISession.Flush()
,数据就不会持久化到数据库中

配置 自动传真
container.Register(c=>DbConfig.Generate(connectionString.BuildSessionFactory())
.As()
.SingleInstance();
container.Register(c=>c.Resolve().OpenSession())
.As()
.InstancePerLifetimeScope();
容器.注册表通用(类型(存储库))
.As(类型(假定))
.InstancePerLifetimeScope();
存储库
公共类存储库:IRepository,其中T:class
{
受保护的只读会话;
公共存储库(ISession会话)
{
会话=会话;
}
公共无效添加(T实体)
{
Session.Save(实体);
}
}
数据库种子(应用程序启动)
公共类数据库种子
{
公共静态无效种子(IContainer容器)
{
var session=container.Resolve();
var userRepo=container.Resolve();
添加(新用户{Id=5,Name=“Test User”});

//session.Flush();提交事务将刷新会话。事务是基础的一部分

-或-

打开NHibernate日志记录,您将看到AutoFac是否处理会话,以及NHibernate是否自行刷新

您已将AutoFac配置为会话应在lifetimescope结束时释放。您在哪里配置lifetimescope应与http请求匹配


更新

我只是自己测试了它,如果会话被释放,会话不会被刷新。这是有道理的,因为您通常使用的事务将在会话被释放之前提交。否则,会话将在事务之外刷新


因此,要么将flushmode设置为“始终”,要么使用事务。正如我在最初的回答中所说,事务是基础的一部分。

提交事务将刷新会话。事务是基础的一部分

-或-

打开NHibernate日志记录,您将看到AutoFac是否处理会话,以及NHibernate是否自行刷新

您已将AutoFac配置为会话应在lifetimescope结束时释放。您在哪里配置lifetimescope应与http请求匹配


更新

我只是自己测试了它,如果会话被释放,会话不会被刷新。这是有道理的,因为您通常使用的事务将在会话被释放之前提交。否则,会话将在事务之外刷新


因此,要么将flushmode设置为“始终”,要么使用事务。正如我在最初的回答中所说,事务是基础的一部分。

我对AutoFac一无所知,因为我最喜欢的DI框架是Spring.NET及其XMLs:)。 但对对象的更改以某种方式没有持续存在的问题我很熟悉。在我得到的所有情况下,它们都与刷新模式和事务有关。我通过以下过程处理这些问题:

首先要检查的是事务。它是否到位?强烈建议您至少执行事务中的所有更新/删除。让我们假设事务已启动


我们进入刷新模式。会话的刷新模式是什么?如果是提交,更改应该被持久化。如果是自动的,更改也必须被持久化。因此,我认为它从来都不是,这需要您使用session.flush()手动刷新它(

我对AutoFac一无所知,因为我最喜欢的DI框架是Spring.NET及其XMLs:)。 但对对象的更改以某种方式没有持续存在的问题我很熟悉。在我得到的所有情况下,它们都与刷新模式和事务有关。我通过以下过程处理这些问题:

首先要检查的是事务。它是否到位?强烈建议您至少执行事务中的所有更新/删除。让我们假设事务已启动


我们进入刷新模式。会话的刷新模式是什么?如果是提交,更改应该被持久化。如果是自动的,更改也必须被持久化。因此,我认为它从来都不是,这需要您使用session.flush()手动刷新它.

正如我所说,我知道将整个事务包装在一个事务中并提交它可以解决问题,但我试图理解为什么一个更简单的解决方案似乎不够。AFAIK
InstancePerLifetimeScope
在web应用中使用时默认为每个HTTP请求的实例。这就是为什么您可以打开NHibernate日志to看看它有什么作用。你说的没错,
Dispose
本身并不会导致所有挂起的命令执行。我原以为这可能是与Autofac相关的对象生存期问题,但在你的测试提示下,我将db init代码移到了控制器上,并经历了相同的行为。不确定我是从哪里得到这个想法的除非另有说明,
Dispose
应该会自动刷新…根据其他人在互联网上的说法,事务确实应该被用作任何操作的标准部分。感谢您花时间响应和测试!正如我所说,这可能会有所帮助,我知道将整个事务包装在一个事务中并提交会解决问题解决这个问题,但我试图理解为什么一个更简单的解决方案似乎不够。当在web应用程序中使用时,AFAIK
InstancePerLifetimeScope
默认为每个HTTP请求的实例。这就是为什么您可以打开NHibernate日志来查看它的功能。您说的
Dispose
没有,这确实是正确的,
container.Register(c => DbConfig.Generate(connectionString).BuildSessionFactory())
    .As<ISessionFactory>()
    .SingleInstance();

container.Register(c => c.Resolve<ISessionFactory>().OpenSession())
    .As<ISession>()
    .InstancePerLifetimeScope();
    
container.RegisterGeneric(typeof(Repository<>))
    .As(typeof(IRepository<>))
    .InstancePerLifetimeScope();
public class Repository<T> : IRepository<T> where T : class
{
    protected readonly ISession Session;
    
    public Repository(ISession session)
    {
        Session = session;
    }

    public void Add(T entity)
    {
        Session.Save(entity);
    }
}
public class DatabaseSeed
{
    public static void Seed(IContainer container)
    {
        var session = container.Resolve<ISession>();
        var userRepo = container.Resolve<IRepository<User>>();
        userRepo.Add(new User { Id = 5, Name = "Test User" });
        
        //session.Flush(); <-- if not called, user will not be persisted!
    }
}