Musings on .NET, architecture and code stuffs from a veteran dev monkey and Sitecore Technology MVP
Showing posts with label nHibernate. Show all posts
Showing posts with label nHibernate. Show all posts
Wednesday, December 1, 2010
Speeding Up NHibernate Startup Time
Thanks to Development With A Dot for this one. Works a treat :)
Labels:
.NET,
nHibernate
Monday, November 8, 2010
nHibernate 3.0 QueryOver - Searching, and Paging at database level
I've been through numerous data-access technologies with .NET - plain old DataReaders & SqlCommands, Code-genned layers around these of various descriptions and varying degrees of horrible, Pile of Code, Typed Datasets, Linq-to-SQL, Lightspeed, LLBLGen Pro, Entity Failwork.
Of all these, nHibernate 3.0 is definitely one of them. No doubt something better is on the horizon and when it looms into view I might take a look. Until then, this is working well for me.
In my humble opinion, NH3 is way better than Linq-to-Fail or infact any other model-based ORF (Object-Relational Failfactory).
That said, I'd like a nicer way of doing multi-field searches; maybe by using an Expression<ICriteria> as a parameter to my search method ?
Here is my search method, abbreviated so as not to cause boredom: -
I'm working on a nicer way of doing this, so stay tuned. That said, the above is fairly readable; I'm just appending additional sections to the WHERE clause where needed.
Hmm.. Anyway, one thing NH3 gives us is database-level paging using the SQL Server ROW_NUMBER function, which is efficient (much more efficient than selecting the whole set into memory and doing the paging there..).
This is nice, except it *only* returns the rows in the page. How do I know how many rows there are in total, so I can set up my pager accordingly ?
This is easy when done at stored procedure level, as I can just run an additional Count(*) SELECT and return an OUT parameter, all in one hit to the database. Am I going to need two hits here ?
As it turns out, the CriteriaTransformer has a "TransformToRowCount" method, which does what we need. This does issue one more SQL statement for the count, and it's submitted separately - so two round trips, not ideal.
And after reading this, the process has been simplified even further with the addition of an extension method. So the previous example can be re-written as just ..
Nice ! But still two database hits. There are two ways to fix this: -
Toodles.
Of all these, nHibernate 3.0 is definitely one of them. No doubt something better is on the horizon and when it looms into view I might take a look. Until then, this is working well for me.
In my humble opinion, NH3 is way better than Linq-to-Fail or infact any other model-based ORF (Object-Relational Failfactory).
- The fluent style works well; it's nice to use
- It's codegen-able like a crazy thing
- It's flexible and very extensible
- It performs - the generated SQL is lean and exactly what you need, it's measurably faster than L2S or Lightspeed
- It isn't Linq-to-SQL
- or a cabbage
That said, I'd like a nicer way of doing multi-field searches; maybe by using an Expression<ICriteria> as a parameter to my search method ?
Here is my search method, abbreviated so as not to cause boredom: -
public IListCustomerSearch(CustomerSearchCriteria criteria, int pageIndex, int pageSize) { IList list = null; using (var session = SessionFactory.OpenSession()) { var query = session.QueryOver (); if (!string.IsNullOrEmpty(criteria.CustomerName)) { MatchMode matchMode; if (criteria.CustomerSearch == CustomerSearchEnum.StartingWith) { matchMode = MatchMode.Start; } else if .. // etc query = query.WhereRestrictionOn(x => x.CustomerName.ToLower()).IsLike(criteria.CustomerName.ToLower(), matchMode); } if (criteria.ActiveOnly) { query = query.And(x => x.Active == true); } if (!string.IsNullOrEmpty(criteria.Address1)) { query = query.And(x => x.Address1.ToLower().StartsWith(criteria.Address1.ToLower())); } // etc
I'm working on a nicer way of doing this, so stay tuned. That said, the above is fairly readable; I'm just appending additional sections to the WHERE clause where needed.
Hmm.. Anyway, one thing NH3 gives us is database-level paging using the SQL Server ROW_NUMBER function, which is efficient (much more efficient than selecting the whole set into memory and doing the paging there..).
list = query.Skip(pageIndex * pageSize)
.Take(pageSize)
.OrderBy(x => x.CustomerName).Asc()
.List();
This is nice, except it *only* returns the rows in the page. How do I know how many rows there are in total, so I can set up my pager accordingly ?
This is easy when done at stored procedure level, as I can just run an additional Count(*) SELECT and return an OUT parameter, all in one hit to the database. Am I going to need two hits here ?
As it turns out, the CriteriaTransformer has a "TransformToRowCount" method, which does what we need. This does issue one more SQL statement for the count, and it's submitted separately - so two round trips, not ideal.
list = query.Skip(pageIndex * pageSize)
.Take(pageSize)
.OrderBy(x => x.CustomerName).Asc()
.List();
int count = CriteriaTransformer.TransformToRowCount(query.UnderlyingCriteria)
.UniqueResult();
And after reading this, the process has been simplified even further with the addition of an extension method. So the previous example can be re-written as just ..
list = query.Skip(pageIndex * pageSize)
.Take(pageSize)
.OrderBy(x => x.CustomerName).Asc()
.List();
int count = query.RowCount();
Nice ! But still two database hits. There are two ways to fix this: -
- Use a transaction
- Use a projection
Toodles.
Labels:
.NET,
nHibernate
Subscribe to:
Posts (Atom)