views:

2040

answers:

3

Anybody know of a way to batch NHibernate queries using NHibernate.Linq like you can do with MultiCriteria and ICriteria objects?

With MultiCriteria I can create something like this:

var crit = session.CreateMultiCriteria()
                  .Add(session.CreateCriteria(typeof(Entity1)).Add(Restrictions.Eq("Property1","Value"))
                  .Add(session.CreateCriteria(typeof(Entity2)).Add(Restrictions.Eq("Property2","Value2"));               

var result = crit.List();
var list1 = (IList)result[0];
var list2 = (IList)result[1];

It would be nice if I replace the CreateCriteria calls with Linq calls and get something like this:

var crit = session.CreateMultiCriteria()
                .Add(session.Linq<Entity1>().Where(x => x.Property1 == "Value1")
                .Add(session.Linq<Entity2>().Where(x => x.Property2 == "Value2");

var result = crit.List();
var list1 = (IList<Entity1>)result[0];
var list2 = (IList<Entity2>)result[1];

We're using the Linq API for most of our other queries and it would be nice to use the same Linq syntax when we need to run MultiCriteria queries as well.

Thanks.

+1  A: 

NHibernate.Linq itself uses NHibernateQueryTranslator to translate from the LINQ expression to an ICriteria. You could do this too, then pass the resulting ICriteria into your IMultiCriteria.

James L
Thanks, I'll have to look into the NHibernateQueryTranslator and see if I can make something work.
Andrew Hanson
A: 

I have a solution that enables both batching a fetching strategies using NHibernate Linq, but the code is king of complex. It's too much to list here. I am going to be talking about it on my blog on devlicio.us pretty soon. I'll update this comment when I write the first post.

EisenbergEffect
I look forward to reading your post.
Andrew Hanson
+2  A: 
var query = from q in session.Linq<Person>()
            where q.FirstName.StartsWith(firstName)
            && q.LastName.StartsWith(lastName)
            && q.Phones.Any(p => p.Number.Contains(phone))
            select q;

// This block of code was found in the NHibernate.Linq source
// using NHibernate.Linq.Visitors;
// using NHibernate.Engine;
System.Linq.Expressions.Expression expression = query.Expression;
expression = Evaluator.PartialEval(expression);
expression = new BinaryBooleanReducer().Visit(expression);
expression = new AssociationVisitor((ISessionFactoryImplementor)session.SessionFactory).Visit(expression);
expression = new InheritanceVisitor().Visit(expression);
expression = CollectionAliasVisitor.AssignCollectionAccessAliases(expression);
expression = new PropertyToMethodVisitor().Visit(expression);
expression = new BinaryExpressionOrderer().Visit(expression);
NHibernateQueryTranslator translator = new NHibernateQueryTranslator(session);
object results = translator.Translate(expression, ((INHibernateQueryable)query).QueryOptions);

// My LINQ query converted to ICriteria
ICriteria resultsCriteria = results as ICriteria;
// Convert to criteria that returns the row count
ICriteria rowCountCriteria = CriteriaTransformer.TransformToRowCount(resultsCriteria);

IList multiResults = session.CreateMultiCriteria()
    .Add(resultsCriteria.SetMaxResults(20))
    .Add(rowCountCriteria)
    .List();

IList people = (IList)multiResults[0];
int resultsCount = (int)((IList)multiResults[1])[0];

from http://rndnext.blogspot.com/2009/05/using-nhibernate-multicriteria-and-linq.html

calebt