缓存 Fluent NHibernate 的 ISessionFactory

3
我们正在开发一款移动应用程序,正在评估使用 NHibernate + Fluent。问题是,第一次创建 ISessionFactory 花费了整整 2 分钟的时间,尽管表结构非常简单(仅有 3 个表)。
但是每次调用后都非常快速。
我想要做的是在应用程序重新启动之间缓存 ISessionFactory,或者以某种方式加速首次创建。
对于能否缓存的任何想法?根据我的阅读,没有太多加速的方法。
3个回答

4
您可以对配置进行序列化和保存,下次使用时加载已保存的配置以减少创建所需的时间。但是,如果您进行更改,则需要删除旧配置并序列化新版本,否则将加载旧的配置。
我记不得如何编写代码来实现这一点了,我会尝试找到一个例子。
编辑: http://vimeo.com/16225792 在这个视频中,Ayende在大约24分钟处讨论了配置序列化。

4
好主意,但是为3个表/实体解析配置和构建会话工厂需要2分钟的时间似乎太长了。我认为这里还有其他问题需要解决,应该先解决这些问题,而不是通过配置序列化来使应用程序更加复杂。 - James Kovacs
是的,我同意,也许他把映射关系放在了与应用程序其他部分相同的程序集中。 - Phill
只有在模拟器和设备上运行时,这2分钟才会发生,如果我们将其作为普通的Windows应用程序运行,则只需要几毫秒。但是配置的序列化是一个好主意。我们尝试了一下,在启动期间反序列化时出现错误,我们正在研究为什么会出现这种情况。 - bryan costanich
有人已经使用流畅的方式或普通基于XML的nhibernate设置使其工作了吗? - bryan costanich
1
是的,我们已经做到了,它减少了近30%的时间,但真正花费时间的是创建会话工厂。 - bryan costanich
显示剩余4条评论

2

将ISessionFactory定义为静态变量(VB中为共享变量),并仅在应用程序启动时实例化一次,是Web应用程序解决这个问题的方法。我知道这可能会对具有内存效率要求的移动应用程序构成挑战,但根据您使用的移动平台,应用程序生命周期可能不会像人们担心的那样短...

    public class NHHelper {
        private static string _connectionString;
        private static ISessionFactory _sessionFactory;

        private static ISessionFactory SessionFactory {
            get {
                if (_sessionFactory == null) {
                            _sessionFactory = Fluently.Configure()
                                .Database(MsSqlConfiguration.MsSql2008.ShowSql()
                                    .ConnectionString(p => p.Is(_connectionString)))
                                .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetAssembly(typeof(NHHelper))))
                                .BuildSessionFactory();
                }
                return _sessionFactory;
            }
        }

// this is called once upon application startup...
        public static void WarmUpSessionFactory(string connectionString) {
            _connectionString = connectionString;
            var factory = SessionFactory;
        }
// this is what you call to get a session for normal usage
        public static ISession OpenSession() {
            return SessionFactory.OpenSession();
        }
    }

我的问题不在于会话工厂在应用程序实例中的持久化,而是在应用程序实例之间变得缓慢。因此,这并没有真正帮助我。我们正在尝试使用缓存来解决这个问题。 - bryan costanich

0

在构建配置和ISessionFactory时,NHibernate会解析配置和映射以构建其运行时数据结构。(这也适用于EF和LINQ-to-SQL,尽管它在上下文中是隐藏的。)虽然几乎没有什么可以做来消除这个成本,但2分钟似乎太长了。计时此代码:

        var stopwatch = new Stopwatch();
        stopwatch.Start();
        var cfg = new Configuration();
        cfg.Configure();
        var sessionFactory = cfg.BuildSessionFactory();
        stopwatch.Stop();
        Console.WriteLine("Startup time was " + stopwatch.ElapsedMilliseconds + "ms");

这是一个演示项目,只有几个类和映射,但在没有调试器附加的情况下需要大约850毫秒。当调试器附加时,需要大约2秒钟。
您是否尝试过对应用程序进行分析以查看它花费了2分钟的时间?

是的,我们已经做过这个,这就是我们发现特定项目时间如此之长的原因。只是为了明确,当我们在非移动模拟器上执行此操作(比如在Windows机器上),只需要毫秒级别的时间。只是在设备上(和模拟器上)它变得如此缓慢。 - bryan costanich
哎呀,我从未尝试在移动设备上运行NHibernate。可能是因为处理器速度较慢、内存大小较小以及不同的运行时环境所致。(我假设你正在运行.NET Compact Framework。)我认为菲尔上面提到的序列化配置值得研究。 - James Kovacs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接