On Oct 1, 7:03 pm, Jason Meckley <[email protected]> wrote:
> I come back to the separation of queries and commands.
So usually you use something like this?
using(var session = factory.OpenSession())
{
session....ExecuteUpdate();
}
using(var session = factory.OpenSession())
{
var entity session..Get<Entity>(id);
...
}
> will go a long way to help alleviate the issue. NH deals with objects,
> not tables/rows. the id of an object is a database artifact within the
> domain model. that is why you evict by object rather than id. I also
> convert the sql query to domain logic.
In my case there are a lot of dynamic: dynamic paged lists, with usr
definied sort column, filter column, filter type.
Also updates logic includ access to a lot of auxilary tables for which
I don't want to create business objects (as they could be used as
filters only in several queries)
>this would mean the object gets
> updated first, then changes are persisted to the database. again
> removing the issue of 2nd db hits and eviction.
>
> This will be your best option to work with the concepts of NH, rather
> than against them.
>
> On Oct 1, 9:15 am, Yauhen <[email protected]> wrote:
>
>
>
> > 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
>
> ...
>
> read more »
--
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.