tags:

views:

32

answers:

1

I am using NHibernate in an MVC 2.0 application. Essentially I want to keep track of the number of times each product shows up in a search result. For example, when somebody searches for a widget the product named WidgetA will show up in the first page of the search results. At this point i will increment a field in the database to reflect that it appeared as part of a search result.

While this is straightforward I am concerned that the inserts themselves will greatly slow down the search result. I would like to batch my statements together but it seems that coupling my inserts with my select may be counter productive. Has anyone tried to accomplish this in NHibernate and, if so, are there any standard patterns for completing this kind of operation?

+1  A: 

Interesting question!

Here's a possible solution:

var searchResults = session.CreateCriteria<Product>()
    //your query parameters here
    .List<Product>();
session.CreateQuery(@"update Product set SearchCount = SearchCount + 1
                      where Id in (:productIds)")
       .SetParameterList("productIds", searchResults.Select(p => p.Id).ToList())
       .ExecuteUpdate();

Of course you can do the search with Criteria, HQL, SQL, Linq, etc.

The update query is a single round trip for all the objects, so the performance impact should be minimal.

Diego Mijelshon
Diego, this is a pretty nice approach - thank you. My worry is still that blocking locks on the Product table could impact the performance of the search as a whole but I guess the only real way to stop this is by processing the updates separately (asynchronously and/or via a queue). I think this solution is pretty elegant and will undoubtedly use it elsewhere. Thanks!
JP
You won't be holding locks if you commit immediately afterwards... a lock-free alternative is to have an insert-only table where you record the Product Ids only, which is then aggregated by another process to update the count.
Diego Mijelshon