Let me clarify slightly :)
Sometimes I have this sequence
1)
session open
session get (hit db)
session update
session get (hit db)

and
some times this one
2) session open
session update
session get (hit db)

In 2nd case first session get (hit db) is missing.
Command (session update ) lies inside separate method
MessagesRepository.Delete.
So I was thinking of some type of uniform. So in both cases I will
need to just call MessagesRepository.GetDetails.
But in 1st this is not true. Because I will need to do Evict. I was
thinking to place it inside MessagesRepository.Delete.
But it is not possible to do this by id. Of course I could write to
methods - MessagesRepository.Delete(id),
 MessagesRepository.Delete(entity) and in 2nd do Evict. 2nd will be
used in 1) sequence of commands. As I understand the most simple way
to
do 1) without evict is using separate sessions. But I was thinking
before that sharing the same session will be more correct for
performance.
So my implementation was based on NHibernate Best Practices with
ASP.NET, 1.2nd Ed.(http://www.codeproject.com/KB/architecture/
NHibernateBestPractices.aspx)





On Oct 1, 4:01 pm, Jason Meckley <[email protected]> wrote:
> in that scenario there is no need to evict, because no entities have
> been loaded. it may be that execute update works like save/update/
> delete/etc. calling the method queues the command. it's not actually
> executed until the session is flushed. example
>
> session open
> session update (update is queued)
> session get (hit db)
> tx.commit/session.flush (update is executed)
>
> if that's the case it would explain why you are getting "stale" data.
>
> Something else to consider is the session/unit of work boundaries and
> practice of command query separation. I have used this with great
> success without fail. In the context of NH  a session should have the
> purpose of getting data (query) or modifing data (command), not both.
> in the context we described we have queries and commands.
>
> at a minimum this should work
> using(var session = factory.OpenSession())
> {
>    using(var tx = session.BeginTransaction())
>    {
>          session....ExecuteUpdate();
>          tx.Commit(); //omitting rollback code, but it should be there
>    }
>    using(var tx = session.BeginTransaction())
>    {
>          var entity session..Get<Entity>(id);
>          Display(entity);
>          tx.Commit(); //omitting rollback code, but it should be there
>    }
>
> }
>
> typically I wouldn't write the code this way either, unless I was
> stuck using webforms. instead I would write it like this
> using(var session = factory.OpenSession())
> using(var tx = session.BeginTransaction())
> {
>    session....ExecuteUpdate();
>    tx.Commit(); //omitting rollback code, but it should be there
>
> }
>
> using(var session = factory.OpenSession())
> using(var tx = session.BeginTransaction())
> {
>    var entity session..Get<Entity>(id);
>    Display(entity);
>    tx.Commit(); //omitting rollback code, but it should be there
>
> }
>
> where each of those would be it's own request. in web MVC it's
> referred to as Post-Redirect-Get. the concept of query command
> separation would apply to rich clients or messsaging as well. the
> implementation may look different though.
>
> On Oct 1, 3:14 am, Yauhen <[email protected]> wrote:
>
>
>
> > I am speaking about your scenario:
> > session open
> > session get (hit db)
> > session update
> > session evict (if you don't evict get pulls for 1st level cache)
> > session get (hit db)
>
> > I want that it looks like
> > session open
> > session update
> > session evict (by it without database hit)
> > session get (hit db)
>
> > So I want some way to evict from 1st level cache by id.
>
> > On Sep 30, 8:26 pm, Jason Meckley <[email protected]> wrote:
>
> > > I don't follow. may be I should back up.
> > > what are you doing now? is it the code your originally posted? if not
> > > please post the actual code.
> > > what is happening?
> > > what do you want/expect to happen?
> > > what do you mean by cache? 1st level cache. also known as the identity
> > > map. or are you referring to 2nd level cache?
> > > I assume the 1st level cache, since you don't have caching enabled in
> > > the mapping.
>
> > > if the entity exists in the 1st level cache and you query the
> > > database, but the object already exists in the cache the cached object
> > > is returned, not the database object. have you run your application
> > > through nhprof? this will give you an excellent idea of what's going
> > > on.
>
> > > On Sep 30, 11:25 am, Yauhen <[email protected]> wrote:
>
> > > > Are there any way to do without additional hit on database? For
> > > > example to make evict by id?
> > > > Because first get seen to me redundant. I need only updated entity not
> > > > original. And method should be as
>
> > > > session get (hit db)
> > > > session update
> > > > session evict (if you don't evict get pulls for 1st level cache)
>
> > > > On Sep 30, 5:58 pm, Jason Meckley <[email protected]> wrote:
>
> > > > > if the next call comes from the same session, then you need to evict
> > > > > the object. example:
> > > > > session open
> > > > > session get (hit db)
> > > > > session update
> > > > > session evict (if you don't evict get pulls for 1st level cache)
> > > > > session get (hit db)
>
> > > > > if the the call comes from a completely different session then you
> > > > > don't need to do anything.
> > > > > session 1: open
> > > > > session 2: open
> > > > > session 2: get (hit db)
> > > > > session1: update
> > > > > session2: get (1st level cache)
> > > > > this is by design
>
> > > > >  if you are expecting this:
> > > > > session 1: open
> > > > > session 2: open
> > > > > session 2: get (hit db)
> > > > > session1: update
> > > > > session2: get (hit db)
> > > > > ...
> > > > > it won't, not without evicting anyway. that is by design. there are 3
> > > > > options to handle that
> > > > > 1. pessimistic concurrency (lock the database row)
> > > > > 2. optimistic concurrency (versioning)
> > > > > 3. call evict on session 2
>
> > > > > typically #2 provides better performance. it requires you to handle
> > > > > the StaleObjectException. #1 can result in command timeouts, so you
> > > > > would need to handle them as well. #3 goes against how NH is designed
> > > > > to operate. it's possible, but not advisable. also you cannot
> > > > > guarantee evict is called before session 1 update.
>
> > > > > On Sep 30, 10:32 am, Yauhen <[email protected]> wrote:
>
> > > > > > I simply need invalidate cache. So next call not get value fro cache
> > > > > > but from real database.
>
> > > > > > On Sep 30, 5:27 pm, Roger Kratz <[email protected]> wrote:
>
> > > > > > > I'm not sure I understand but...
>
> > > > > > > << [...] Session is the same betwwen calls. [...]>>
> > > > > > > << [...] query.ExecuteUpdate(); [...] >>
>
> > > > > > > Are you expecting your call to ExecuteUpdate to update the state 
> > > > > > > inside your ISession? I don't think that will work.
>
> > > > > > > Session keeps a first level cache. The state of this cache won't 
> > > > > > > be updated when calling ExecuteUpdate AFAIK - no entities are 
> > > > > > > returned.
>
> > > > > > > /Roger
>
> > > > > > > -----Original Message-----
> > > > > > > From: [email protected] [mailto:[email protected]] 
> > > > > > > On Behalf Of Yauhen
> > > > > > > Sent: den 30 september 2010 16:10
> > > > > > > To: nhusers
> > > > > > > Subject: [nhusers] Re: NHibernate cache
>
> > > > > > > so nobody has ideas?
>
> > > > > > > On Sep 28, 12:50 pm, Yauhen <[email protected]> wrote:
> > > > > > > > I have found very strange effect when using nhibernate.
> > > > > > > > I am trying to do one clever update operation. Then read saved 
> > > > > > > > data
> > > > > > > > from database.
> > > > > > > > Operations are mostly based on sql queries. In database data 
> > > > > > > > are ok.
> > > > > > > > But by some strange reason nhibernate uses cached old data.
> > > > > > > > Operations are described like following:
> > > > > > > > <class name="Message"  table="Messages" >
> > > > > > > >                 <id name="Id" type="Int32" column="Id">
> > > > > > > >                         <generator class="identity"/>
> > > > > > > >                 </id>
> > > > > > > >                 <property name="Subject" column="Subject" 
> > > > > > > > type="String"/>
> > > > > > > >                 <property name="CategoryId" column="CategoryId" 
> > > > > > > > type="Int32"/>
>
> > > > > > > > <sql-query name="Message.Delete">
> > > > > > > >     <synchronize table="Messages"/>
> > > > > > > >     UPDATE Messages
> > > > > > > >     SET CategoryId = (  /* long select to decide to which 
> > > > > > > > category to
> > > > > > > > move*/
> > > > > > > >                                )
> > > > > > > >      WHERE Id = :messageId
> > > > > > > >   </sql-query>
>
> > > > > > > >  <sql-query name="Message.GetDetails">
> > > > > > > >     <return alias="msg" class="Message"/>
> > > > > > > >         SELECT  {msg.*}
> > > > > > > >         FROM Messages {msg}
> > > > > > > >         WHERE msg.Id = :messageId
> > > > > > > >   </sql-query>
>
> > > > > > > > when calling delete/update query I use syntax like following
> > > > > > > >  using (ITransaction trans = _session.BeginTransaction())
> > > > > > > >             {
> > > > > > > >                 IQuery query =
> > > > > > > > _session.GetNamedQuery("Message.Delete");
> > > > > > > >                 query.SetParameter<IdT>(paramName, id);
> > > > > > > >                 query.ExecuteUpdate();
> > > > > > > >                 trans.Commit();
>
> > > > > > > >                  _session.Flush();
> > > > > > > >             }
> > > > > > > > when calling read:
> > > > > > > > IQuery query = _session.GetNamedQuery("Message.GetDetails");
> > > > > > > > query.SetInt32("messageId", messageId);
> > > > > > > > query.List<Message>();
>
> > > > > > > > Session is the same betwwen calls. Caching occurs somewhere 
> > > > > > > > inside
> > > > > > > > NHibernate.Loader
>
> > > > > > > > obj = session.GetEntityUsingInterceptor(key);
>
> > > > > > > --
> > > > > > > You received this message because you are subscribed to the 
> > > > > > > Google Groups "nhusers" group.
> > > > > > > To post to this group, send email to [email protected].
> > > > > > > To unsubscribe from this group, send email to 
> > > > > > > [email protected].
> > > > > > > For more options, visit this group 
> > > > > > > athttp://groups.google.com/group/nhusers?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en.

Reply via email to