0

According to this question and corresponding answers, it is highly recommended for NHibernate to use transactions even for reading operations. I'm not sure about when fetching data is happened. Imagine we have a simple reading operation from MSQL Server database:

var topics = _topicRepository.Read(0, 10);

where read method of topic repository simply returns enumeration of values:

public IEnumerable<Topic> Read(int beginIndex, int amount)
{
    return _session.Query<Topic>().Skip(beginIndex).Take(amount);
}

As I understand, NHibernate won't extract values from database (according to lazy initialization) until we call ToList() or do any other manipulations with data. But what is going on when we wrap this Read call into transaction and fetch data by calling ToList() until transaction is commited?

transaction.Begin();
var topics = _topicRepository.Read(0, 10).ToList();
transaction.Commit();

Calling ToList() is going to make database request immediately (it means that NHibernate should run transaction, which will contain single read operation), than what is going to be commited? And won't it be something like new transaction inside transaction? Thanks in advance for explanation.

Community
  • 1
  • 1
Eadel
  • 3,797
  • 6
  • 38
  • 43

1 Answers1

2

The reading operation will take place immediately. If you want to defer them, you should consider using the .ToFuture() method.

Also, make sure you read this (and other parts of it) pitfall of nhibernate while you use nhibernate.

Mihalis Bagos
  • 2,500
  • 1
  • 22
  • 32
  • What is the purpose to wrap them explicity in transaction then? – Eadel Oct 04 '12 at 06:37
  • At the end of the transaction, all your futures will be executed with a single roundtrip to the db – Mihalis Bagos Oct 04 '12 at 13:21
  • Well, will it be the best solution to use `ToFuture()` and wrap every call to DB in `Begin()` and `Commit()`? It seems that eager fetching makes working with transaction object redundant, isn't it? – Eadel Oct 04 '12 at 17:30
  • Again, if you use futures with transaction, you will only make one round trip to the database to get the data. For example if you need to also count the things you have, you would instead get 2 round trips. If you also needed some related entities you would make 3 round trips, etc. – Mihalis Bagos Oct 04 '12 at 20:26
  • I understood it, I don't understand why it is better (really better?) to use transaction for eager operations, because they are executed before commiting. – Eadel Oct 05 '12 at 07:07
  • 1
    Transactions as a struct in general, is so that you can update in one batch, or download in one batch. Updating in one batch means that you can controll an all-or-nothing scenario, if some updates fail. Downloading, means you can better handle caching, and of course the performance of the batch download itself – Mihalis Bagos Oct 05 '12 at 08:05
  • You explained everything very well, but you didn't answer one question yet :) Do I need to wrap eager call to database into transaction? The code is in the first post. – Eadel Oct 06 '12 at 10:41
  • 1
    The end of the transaction, is when the round-trip happens, so if you use futures then you do need to wrap inside a transaction. Otherwise you get objects similar to IQueryable - they contain the query but not the actual data – Mihalis Bagos Oct 08 '12 at 10:37