Flushing with Castle ActiveRecord - nhibernate

i saw that i can use SessionScope and have inserts
inside the scope of the SessionScope and do flush at the end of the scope.
my question is if i can define in some way that after, let's
say, every 10 insertions/saves of objects, that they will automatically
be flushed to the db.
in other words i want to be able to configure the way i use flush with castle active record.
p.s: is there any way to configure cascading behavior for objects like in NHibernate?

You could hook up your own IPostInsertEventListener where you keep track of insertion count and flush accordingly. But I recommend against this unless you have some very good reasons to do so.
The relevant attributes have a Cascade property to set cascading behavior. See for example HasMany.

Related

Problems with NHibernate FlushMode Never

We're building a large application with NHibernate as ORM layer. We've tried to apply as many best practices as possible, among which setting FlushMode to Never. However, this is giving us pain, for example the following scenario:
There is a table with an end date column. From this table, we delete the last (by end date) record:
The record is deleted;
After the delete, we do a (repository) query for the last record (by end date);
This last record is updated because it's the new active record.
This is a very simple scenario, of which many exist. The problem here is that when we do the query, we get the deleted record back, which of course is not correct. This roughly means that we cannot do queries in business logic that may touch the entity being inserted or deleted, because its resp. not there yet or still there.
How can I work with this scenario? Are there ways to work around this without reverting the FlushMode setting or should I just give up on the FlushMode setting all together?
How can I work with this scenario? Are there ways to work around this
without reverting the FlushMode setting
FlushMode.Never does not prevent you from manually calling Flush() when you want to deal with up-to-date data. I guess it is the way to work this scenario without changing the FlushMode
or should I just give up on the FlushMode setting all together?
Could you provide some reference on FlushMode.Never being a good practice in the general case ? Seems like FlushMode.Never is fit when dealing with large, mostly readonly, sets of objects.
http://jroller.com/tfenne/entry/hibernate_understand_flushmode_never
FlushMode.Never is a best practice only when you absolutely require fine-grained control. FlushMode.Auto will cover 99.99% of the cases without a problem. That said, decorating you CUD operations with a ISession.FLush() will not hurt as it only involves a database roundtrip if there are any CUD actions in the internal action queue
Flush mode Never means NHibernate will never flush the session, it's up to you to do that. So, session.Delete() will not actually delete the record from database, just mark the object for delete in session's cache. You can force a flush by calling session.Flush() after calling session.Delete().
I think Auto is a better option, with Auto, NHibernate will flush the session automatically before querying for data.

Why is NHibernate saving objects when I never execute session.Save?

I'm using NHibernate with Fluent NHibernate.
I have code where I start a transaction, then I enter a loop which creates several objects. For each object I check certain conditions. If these conditions are met, then I execute a session.SaveOrUpdate() on the object. At the end of the loop, I issue a commit transaction.
I have a breakpoint set on the session.SaveOrUpdate command, proving that it is never reached (because the conditions have not been met by any of the objects in the loop). Nevertheless, when the transaction is committed, the objects are saved!
I am using an AuditInterceptor and have set a breakpoint in the OnSave method. It is being called, but the stack trace only traces back to the statement that commits the transaction.
There are no objects of any kind that have had SaveOrUpdate executed on them at this point, so cascading doesn't explain it.
Why is NHibernate saving these objects?
From NHibernate ISession.Update thread:
It's the normal and default behavior:
Hibernate maintains a cache of Objects
that have been inserted, updated or
deleted. It also maintains a cache of
Objects that have been queried from
the database. These Objects are
referred to as persistent Objects as
long as the EntityManager that was
used to fetch them is still active.
What this means is that any changes to
these Objects within the bounds of a
transaction are automatically
persisted when the transaction is
committed. These updates are implicit
within the boundary of the transaction
and you don’t have to explicitly call
any method to persist the values.
From Hibernate Pitfalls part 2:
Q) Do I still have to do Save and
Update inside transactions?
Save() is only needed for objects that
are not persistent (such as new
objects). You can use Update to bring
an object that has been evicted back
into a session.
From NHibernate's automatic (dirty checking) update behaviour:
I've just discovered that if I get an
object from an NHibernate session and
change a property on object,
NHibernate will automatically update
the object on commit without me
calling Session.Update(myObj)!
Answer: You can set Session.FlushMode to
FlushMode.Never. This will make your
operations explicit ie: on tx.Commit() or session.Flush().
Of course this will still update the
database upon commit/flush. If you do
not want this behavior, then call
session.Evict(yourObj) and it will
then become transient and NHibernate
will not issue any db commands for it.
It's to do with the sessions flush mode being FlushMode.Commit (default). When the transaction is committed any changes made to objects within the session are saved and the changes persisted.
There's a FlushMode property on the session that you can set. If you want a readonly transaction specify FlushMode.Manual.
Hope this helps!

NHibernate: What are child sessions and why and when should I use them?

In the comments for the ayende's blog about the auditing in NHibernate there is a mention about the need to use a child session:session.GetSession(EntityMode.Poco).
As far as I understand it, it has something to do with the order of the SQL operation which session.Flush will emit. (For example: If I wanted to perform some delete operation in the pre-insert event but the session was already done with deleting operations, I would need some way to inject them in.)
However I did not find documentation about this feature and behavior.
Questions:
Is my understanding of child sessions correct?
How and in which scenarios should I use them?
Are they documented somewhere?
Could they be used for session "scoping"?
(For example: I open the master session which will hold some data and then I create 2 child-sessions from the master one. I'd expect that the two child-scopes will be separated but the will share objects from the master session cache. Is this the case?)
Are they first class citizens in NHibernate or are they just hack to support some edge-case scenarios?
Thanks in advance for any info.
Stefando,
NHibernate has not knowledge of child sessions, you can reuse an existing one or open a new one.
For instance, you will get an exception if you try to load the same entity into two different sessions.
The reason why it is mentioned in the blog, is because in preupdate and preinsert, you cannot load more objects in the session, you can change an allready loaded instance, but you may not navigate to a relationship property for instance.
So in the blog it is needed to open a new session just because we want to add a new auditlog entity. So in the end it's the transaction (unit of work) that manages the data.

NHibernate: Session.Save and Transaction.Commit

Is there a difference between Session.Save and Transaction.Commit ?
When I should use which?
It seems that sometimes Session.Save must use in conjunction with Transaction.Commit, sometimes no. Can anyone tell why this is so?
They're differenrt-- Session.Save saves an object and Transaction.Commit commits a bunch of work (multiple Gets, Loads, Saves, Updates, etc).
You'll want to use both. Here's a quick explanation with a link for more reading. The NHibernate documentation says the following:
In an ISession, every database operation occurs inside a transaction
that isolates the database operations (even read-only operations).
If you don't explicitly define your transaction, one will be created implicitly every time you read from or write to the database. Not very efficient. So even if you're just reading, you'll want to put everything inside a transaction and commit the transaction when you're done. Ayende Rahien explains further in this blog post.
When you look at some code samples out there, it may seem like people aren't using transactions but they may just be beginning/committing the transaction outside of the code you're looking at. In my ASP.Net MVC app, for example, I use an action filter (TransactionAttribute) to handle the transaction outside of my Controller Actions.

how to create a readonly session in nHiberate?

Is it possible to creat a readonly connection in nHibernate ?
Read-only : where nHibernate will not flush out any changes to the underlying database implicitly or explicitly.
When closing a nhibernate connection it does automatically flush out the changes to the persistent object.
Setting the flush mode to never is one way - but is reversable (i.e some code can reset the flush mode).
I think you've already found the solution, setting flush mode to never. Yes, it is changeable but even if it wasn't, code could simply create another session that had a different flush mode.
I think the appropriate solution is to suggest read-only with session.FlushMode = FlushMode.Never and enforce it by using a connection to the database that only has SELECT permissions (or whatever is appropriate for your situation). Maintaining separate ISessionFactory factories might help by allowing something like ReadOnlySessionFactory.Create().
Take a look at Read Only entities that became available in NHibernate 3.1 GA
https://nhibernate.jira.com/browse/NH-908
There is a newer readonly feature in NHibernate (I don't know which version, but it's in 3.3.0 for sure). You can set the session to read only using this:
session.DefaultReadOnly = true
It disables the cache for old values and therefore improves performance and memory consumption.
There is a chapter about read-only entities in the NHibernate reference documentation.
Accumulating updates, and just never flushing seems like a bad solution to me.
I posted a similar question. The solution provided uses a different approach. All the events are set to empty, and thus ignored. My feeling is that it's a better approach.
I am surprised that this is not easier to do. I like the entity framework approach of using an extension method .AsNoTracking() which ensures that read only queries remain that way.
How to create an NHibernate read-only session with Fluent NHibernate that doesn't accumulate updates?