tags:

views:

213

answers:

2

Hey guys,

I'm somewhat new to NHibernate, so this question may be a no-brainer. Anyway, I'm replacing a project at work that uses ADO.NET that will now be using NHibernate(With LinqToNhibernate). This has worked fine so far, but I've run up against a function that needs to search through a large amount of data(about 200,000 records, test each record using a very specific algorithm(something too complicated for LINQ), and if it matches the criteria I want to add it to the results list. In ADO.NET I used a data reader so I wouldn't have to load all the results in memory. Is there an equivalent way to do this in NHibernate? Would the lazy loading be used for this? Thanks!

A: 

As you might know, when using NHibernate you have to approach working with data in a completely different manner. You're no longer with 'raw data' that comes from the DB like you do in ADO.NET; rather you're working with an OO view on your data.

You do not query the database / tables in NHibernate, but instead, you're querying your entities.

I think that the solution for your problem, can be found in projections. With a projection, you can create your query in NHibernate (using HQL or the ICriteria API).
But, before you execute the query, you specify, via a projection, which properties you're interested in.
NHibernate will then execute a query which retrieves only those properties. This also means that it is not really the entities that are returned. It is rather a DTO that is returned.

So, you will have to create a class which will act as this 'DTO'. It only has the properties that you're interested in, and you also have to 'import' this class so that it is known to NHibernate.

A while ago, I explained on SO how you could use projections. It can be found here

Frederik Gheysels
A: 

Ok from what I remember with the ISession.CreateQuery you can return a list or an enumerable. The List will load all of them into memory (I believe). The IEnumerable will issue a statement to the server to retrieve all of the Ids from the server. Every time you iterate through the ienumerable, it'll check the cache and if it's not in the cache, it'll issue a database call to retrieve the information.

Neither of them is what you want. You either use a ton of memory or hammer the DB.

I really sounds like you're trying to do some kind of ETL operation. Your best bet is to keep a couple of specialized pieces of code around to handle this situation.

If you insist on using NHibernate I would just page through the results in manageable chunks and use stateless sessions here:

http://davybrion.com/blog/2008/10/bulk-data-operations-with-nhibernates-stateless-sessions/

Min
Hey, sorry--I forgot to mention I'm using LinqToNhibernate so I don't use queries(other than Linq).
Austin
I don't see what the problem is of using HQL or ICriteria as well if you abstract all your data-access away in a repository.AFAIK, LinqToNhibernate isn't very mature yet ...
Frederik Gheysels
Frederik, I'm not using the repository pattern because I haven't yet found a need for it. It's easiest right now just to manage the session and queries in the Business layer. And yea, I've found some limits in LinqToNhibernate that need to be worked out(no joins), but so far it's worked very well.
Austin
In linq you can still do a Take - Skip operations in order to do paging in order to handle your memory.
Min
Thanks! I think the Take operation will probably work--I remember now reading about that extension.
Austin