简体   繁体   中英

nhibernate multiple winforms applications

I'm a little confuse with nhibernate and cache management. I have this situation. We are developing a set of win forms applications using nhibernate and oracle database. What happen? when a application modifies data in a particular pc. the modified data is not reflected in other pc. It's like nhibernate holds the data in the cache. But by configuration i think that cache is disabled.

A couple of things. The session factory is created once in the application. It is expensive to create. And the session is opened once too, and re opened when, for example, and exception occurs. I know that opening the session once is not a best practice, but for now is what we have.

Is there a way to force nhibernate to always retrieve data from the database. We can lose performace, i know. But it is important to retrieve data updated by other applications. Or do you have any suggestion to manage the situation.

This is my hibernate configuration

<?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>

Thanks in advance. I don´t know what else i can show to help me solve this problem. I beleave is a configuration problem.

Pd: we are using generic repository from Besnik. http://code.google.com/p/genericrepository/

--- edited ----

This is how i use transactions

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

transaction class

    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)
        {

            ******
        }
    }

this is how i register IUnitOfWork

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

This is how besnik use unit of work when i insert the data (taken from source code)

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

Data are persisted in the database when you commit a transation ( of course you should modify something). You are not using any second level cache so the only cache you are potentially hitting is the first level cache, during for the scope of a session. So you probably need to imrove the session management on your app, to see things changing ( are your session during too much? ) otherwise the entities picked up once stay in session staled. Have a look at this discussion to improve your strategy.

By default NH flushes session (sends modified data to database) when ITransaction.Commit() method is called. This behavior is controlled by the FlushMode enumeration. It's not clear from your question when you open and commit transaction but you can try to call session.Flush() to force NH persist your changes immediately.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM