开发者

Why is a session.Clear() needed to reflect the changes in the db in the this example?

I have the following code:

public class A
{
    private ISessionFactory _sf;
    A(ISessionFactory sf)
    {
        _sf = sf;
    }

    public void SomeFunc()
    {
        using (var session = _sf.OpenSession())
        using (var transaction = session.BeginTransaction())
        {
            // query for a object
            // change its properties
            // save the object

            transaction.commit();
        }
    }
}

Its used as follows in a unit test

_session.CreateCriteria ... // some setting up values for this test

var objectA = new A(_sessionFactory);
objectA.SomeFunc();

// _session.Clear();

var someVal = _session.CreateCriteria ... // retrieve value from db to 
                                   //check if it was set to the 
                                   //proper value
                                   //it uses a restriction on a property
                                   //and a uniqueresult to get the object.
                                   //it doesnt use get or load.

Assert.That(someVal, Is.EqualTo(someOtherValue)); // this is false as long 
                                   //as the _session.Clear() is commented. 
                                   //If uncommented, the test passes

I am testing against a sqlite file database. I开发者_如何学编程n my tests I make some changes to the db to setup it up properly. I then call SomeFunc(). It makes the required modifications. Once I am back in my test, the session however doesnt get the updated values. It still returns the value as was before calling SomeFunc(). I have to execute _session.Clear() to have the changes reflect in my assertion in the test.

Why is this needed?

Edit: cache.use_second_level_cache and cache.use_query_cache are both set to false

Edit2: Read the following statements in the NH Documentation.

From time to time the ISession will execute the SQL statements needed to synchronize the ADO.NET connection's state with the state of objects held in memory. This process, flush, occurs by default at the following points

* from some invocations of Find() or Enumerable()
* from NHibernate.ITransaction.Commit()
* from ISession.Flush()

And in section 10.1 it says,

Ensure you understand the semantics of Flush(). Flushing synchronizes the persistent store with in-memory changes but not vice-versa.

So, how do I get the in memory objects to get updated? I understand that objects are cached per session. But executing a UniqueResult() or a List() should sync with the db and invalidate the cache, right?

What I cannot understand is why is the session reporting stale data?


It depens on what king of operations do you make. NHibernate has first level cache by default. It uses cache to get entities by ID and so on.


The in memory view of objects (the level 1 cache) is per session.

A takes an ISessionFactory and opens its own session with its own transaction scope.

Even if the contents of the ISession used in SomeFunc are flushed to the database, _session will not see those changes until its level 1 cache is cleared.


You have two sessions. One is in A.SomeFunc, and the other is in your unit test. Each session has it's own instance of the entities in the session-cache (1st level cache). The sessions do not communicate or coordinate with each other. When one session writes its changes, the other session isn't notified. It still has it's own outdated instance in its session cache.

When you call _session.Clear(), you make the session "forget" everything by clearing the session cache. When you re-query, you are reading fresh data from the database, which includes the changes from the other session.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜