【问题标题】:nhibernate multiple winforms applications休眠多个winforms应用程序
【发布时间】:2012-02-16 12:51:28
【问题描述】:

我对休眠和缓存管理有点困惑。 我有这种情况。我们正在开发一组使用 nhibernate 和 oracle 数据库的 win forms 应用程序。 发生什么事?当应用程序修改特定 PC 中的数据时。修改后的数据不会反映在其他电脑上。这就像 nhibernate 将数据保存在缓存中。但是通过配置我认为缓存被禁用。

有几件事。会话工厂在应用程序中创建一次。创建成本很高。并且会话也打开一次,并在例如发生异常时重新打开。我知道打开会话一次并不是最佳做法,但目前我们已经做到了。

有没有办法强制 nhibernate 总是从数据库中检索数据。我们可能会失去性能,我知道。但重要的是检索由其他应用程序更新的数据。 或者您对处理这种情况有什么建议。

这是我的休眠配置

<?xml version="1.0" encoding="utf-8"?>
<!-- 
This template was written to work with NHibernate.Test.
Copy the template to your NHibernate.Test project folder and rename it in hibernate.cfg.xml and change it 
for your own use before compile tests in VisualStudio.
-->
<!-- This is the System.Data.OracleClient.dll provider for Oracle from MS -->
<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
  <reflection-optimizer use="true"/>
  <session-factory name="NHibernate.Test">
    <property name="connection.driver_class">NHibernate.Driver.OracleClientDriver</property>
    <property name="connection.connection_string">
      *******
    </property>
    <property name="show_sql">false</property>
    <property name="dialect">NHibernate.Dialect.Oracle10gDialect</property>
    <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
    <property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
    <property name="cache.use_query_cache">false</property>
    <property name="cache.use_second_level_cache">false</property>
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
  </session-factory>
</hibernate-configuration>

提前致谢。 我不知道我还能展示什么来帮助我解决这个问题。我相信是配置问题。

Pd:我们正在使用 Besnik 的通用存储库。 http://code.google.com/p/genericrepository/

---已编辑----

这就是我使用交易的方式

public Pedido Crear(Barra barra, Casillero casillero, Empleado empleado, String codigoEmpleado)
        {
            DateTime fecha = DBService.GetCurrentDateTime();
            Pedido pedido = new Pedido
                                {
                                    Barra = barra,
                                    Casillero = casillero,
                                    Empleado = empleado,
                                    EmpleadoCodigo = codigoEmpleado,
                                    FechaCreacion = fecha
                                };
            Transaction.Transaction.Execute(() => pedidoRepository.Insert(pedido));
            return pedido;
        }

PedidoRepository

namespace Services.Repository.Hibernate
{
    /// <summary>
    /// Implementación del repositorio
    /// </summary>
    class PedidoRepositoryImplementation : GenericRepository<Pedido, long>, PedidoRepository
    {

        /// <summary>
        /// Constructor
        /// </summary>
        public PedidoRepositoryImplementation(IUnitOfWork unitOfWork, ISpecificationLocator specificationLocator)
            : base(unitOfWork, specificationLocator)
        {
        }
    }
}

事务类

    public sealed class Transaction
    {

        public static void Execute(Action transactionalAction, Action<Exception> onException = null)
        {
            if (onException == null)
                onException = WhenException;
            if (transactionalAction != null)
                using (ITransaction transaction = DI.Get<IUnitOfWork>().BeginTransaction())
                {
                    try
                    {
                        transactionalAction();
                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {

                        if (transaction != null)
                            transaction.Rollback();
                        DI.Get<Logger>().exception(ex);
                        IUnitOfWork uwork = DI.Get<IUnitOfWork>();
                        var session = (NHibernate.ISession)ReflectionUtils.GetPropertyValue(uwork, "Session");
                        var last = session;
                        session = session.SessionFactory.OpenSession();
                        ReflectionUtils.SetPropertyValue(uwork, "Session", session);
                        last.Close();
                        last.Dispose();
                        onException.Invoke(ex);
                    }
                }
        }

        private static void WhenException(Exception ex)
        {

            ******
        }
    }

这就是我注册 IUnitOfWork 的方式

//Register the Hibernate Factory
            builder.Register(i => new NHibernateUnitOfWorkFactory(hibernateFilePath));
            builder.Register(i => DI.Get<NHibernateUnitOfWorkFactory>().BeginUnitOfWork()).As<IUnitOfWork>().SingleInstance();

这就是我插入数据时 besnik 使用工作单元的方式(取自源代码)

 public virtual void Insert(TEntity entity)
                {
                        this.UnitOfWork.Insert<TEntity>(entity);
                }

【问题讨论】:

    标签: c# hibernate nhibernate


    【解决方案1】:

    当您提交事务时,数据会保存在数据库中(当然您应该修改某些内容)。您没有使用任何二级缓存,因此您可能会遇到的唯一缓存是一级缓存,在会话范围内。因此,您可能需要改进应用程序上的会话管理,以查看事情的变化(您的会话时间是否过多?)否则一旦在会话中拾取的实体就会过时。 查看this discussion 以改进您的策略。

    【讨论】:

    • 感谢您的回答。是的,会议时间很多。如果没有出现异常,则一直持续到应用程序关闭。
    • 也许你觉得这个答案有用:stackoverflow.com/questions/874981/…
    • 保持会话的持续时间较短 - 就好像它是 Web 应用程序中每个请求的会话一样。如果您将会话包装在 using 语句中,则不需要显式调用 session.flush。一级缓存仅在会话期间持续。
    • 另外,您使用的是什么并发模型?您是否在表上定义了版本控制列?如果您不这样做,其他应用程序实例在尝试进行更新时不会知道它们有过时的数据。
    • 谢谢尼克瑞恩。我改善了会话的持续时间,并且效果很好。而且我不是版本控制,所以实施是个好主意。
    【解决方案2】:

    默认情况下,当调用 ITransaction.Commit() 方法时,NH 会刷新会话(将修改后的数据发送到数据库)。此行为由 FlushMode 枚举控制。当您打开并提交事务时,您的问题尚不清楚,但您可以尝试调用 session.Flush() 以强制 NH 立即保留您的更改。

    【讨论】:

    • 数据提交良好。我使用 oracle 工具看到了数据库中反映的更改。我认为这不是问题。我将编辑我的答案并向您展示我如何使用交易
    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 2011-12-20
    • 1970-01-01
    相关资源
    最近更新 更多