【问题标题】:Why is my ISession not flushed automatically when using Autofac?为什么使用 Autofac 时我的 ISession 没有自动刷新?
【发布时间】:2012-07-25 09:11:03
【问题描述】:

概述

我正在尝试连接 Autofac 以帮助在我的 MVC 4 RC 项目中管理 NHibernate 的 ISession。据我了解,Autofac 应该按照我配置的方式在每个 HTTP 请求结束时调用ISession.Dispose(见下文)。但是,情况似乎并非如此——如果我不调用ISession.Flush(),则数据不会保存在数据库中。

配置

Autofac

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

数据库种子(Application_Start)

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!
    }
}

结束语

我知道我应该将其包装在交易中。但是,我想在进入更复杂的场景之前先掌握基础知识,我很困惑为什么上面的方法不能像我预期的那样工作......

(作为旁注,我尝试运行 Whitebox,Autofac 的“分析器”,但它在我身上失败了,但有一些例外(发布在 Autofac 组@Google 上),所以我不完全确定它是否是 Autfac这是在取笑我或 NHibernate :-)

【问题讨论】:

    标签: nhibernate asp.net-mvc-4 autofac


    【解决方案1】:

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

    - 或者 -

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

    您将 AutoFac 配置为应在生命周期结束时释放会话。你在哪里配置lifetimescope应该匹配一个http请求?


    更新

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

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

    【讨论】:

    • 正如我所说,我知道将整个事物包装在事务中并提交它会解决问题,但我试图理解为什么更简单的解决方案似乎不够。在 Web 应用程序中使用时,AFAIK InstancePerLifetimeScope 默认为每个 HTTP 请求的实例。
    • 这就是为什么您可以打开 NHibernate 日志以查看它的作用。
    • 您确实正确地说Dispose 本身并不会导致所有待处理的命令执行。我认为这可能是一些与 Autofac 相关的对象生命周期问题,但在您的测试提示下,我将 db-init 代码移至控制器并遇到了相同的行为。不知道我从哪里得到Dispose 应该自动刷新的想法,除非另有说明......从其他人在互联网上的说法来看,交易确实有望用作任何操作的标准部分。感谢您抽出宝贵时间回复和测试!
    【解决方案2】:

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

    首先要检查的是交易。到位了吗?强烈建议您至少在事务中进行所有更新/删除。让我们假设事务确实开始了。

    我们进入冲洗模式。会话的刷新模式是什么?如果是 Commit,则应保留更改。如果是 Auto,则还必须保留更改。所以我认为它是 Never,这需要您使用 Session.Flush() 手动刷新它。

    【讨论】:

    • 问题是我根本没有使用事务,只是在做ISession.Save(something) 并希望在处理ISession 时最终会刷新/持久化。现在我有了事务(仍然使用FlushMode.Auto),问题已经解决了,我可以继续做更有趣的事情:-)
    猜你喜欢
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    相关资源
    最近更新 更多