Late evaluation with NHibernate QueryOver - nhibernate

NHibernate.Linq returns IQueryable giving me late evaluation. Can this also be done with QueryOver?
Update:
I will use it to define lots of queries where only a subset would be used. Therefor Future is not the solution, which would execute them all.
I like the IQueryable (IEnumerable) return type from NHibernate.Linq, that will never execute the query if never used.

Firstly, even QueryOver is just a set of definitions to be later converted to the SQL statement. So until you are working with a reference to a
IQueryOver<Entity, Entity> ab = session.QueryOver<Entity>();
and not calling List<Entity>() ... the execution is deferred. That's also how you can use the Detached queries 16.1. Structure of a Query
QueryOver<Cat> query = QueryOver.Of<Cat>()
.Where(c => c.Name == "Paddy");
Another powerful feature is Future. This represents a very easy way how to put few queries on the stack, and only when first of them is required... all are executed and passed to DB Server as a batch. Read here more: NHibernate Futures
They essentially function as a way to defer query execution to a later
date, at which point NHibernate will have more information about what
the application is supposed to do, and optimize for it accordingly
The biggest difference is that it cannot be returned as IQueryable when using QueryOver
EDIT: Extend on a question update
While IQueryable<TEntiy> could be returned only from a session.Query<TEntity>() and not when using QueryOver, ICriteria, HQL ... the same behavior could not be reached when using QueryOver.

Related

IQueryable Extension to Generate Temporal Table "AS OF" Queries

Having failed to find a satisfying solution, let me post this here:
We're using NHibernate as our ORM and are just beginning to use Sql Server temporal tables. We therefore need some kind of extension to IQueryable (or the HQL Builder or an InterceptingProvider or something) that will allow us to add the "AS OF" clause to our queries, something like
var results = session.Query<Company>
.Where(c => c.Name == "FogCreek")
.AsOf(DateTime.Today.AddYears(-1));
I've been struggling with it too and gave up as I lost too much time trying to find better approach...
So far I've injected FOR SYSTEM_TIME AS OF into SQL using custom HqlGeneratorForMethod but this gave me invalid SQL expression. So I had to fix it in OnPrepareStatement. This is hacky and not elegant solution but works for most simple cases.
Please look at my solution here and feel free to reply if you find better solution

JPA -- named-query vs query

One way of conducting an SQL query is the defined NamedQuery in JPA:
Query query = entityManager.createNamedQuery("Users.findByName");
An alternative to this is running it without defining a NamedQuery:
Query query = entityManager.createQuery("SELECT SELECT u FROM Users u");
From what i see, NamedQuery is favorable for it is defined at one-place-for-all in the entity class and is available to a pojo that has a use for it without getting into SQL.
Are there any differences between the two?
The only difference is that one is a String that only can be used in the class where is declared, the one of your second example
Query query = entityManager.createQuery(" SELECT u FROM Users u");
The NamedQueries can be used in different DAO without need to define them again, just call and PersistenceProvider will find them using #NamedQueries - #NamedQuery, or xml files when you define them.
Basically a named queries are a powerful tool for organizing query
definition and improving application performance.
Also a good important stuff is that some provider processed the JPQL inside the namedqueries at the startup time, this gives a hit on the performance, in the second case that you set in yout question, persistence provider is not aware of the query existence and does not have the chance to process it on startup and need to run the process when is required.

NHibernate: How to select the root entity in a projection

Ayende describes a really great way to get page count, and a specific page of data in a single query here:
http://ayende.com/blog/2334/paged-data-count-with-nhibernate-the-really-easy-way
His method looks like:
IList list = session.CreateQuery("select b, rowcount() from Blog b")
.SetFirstResult(5)
.SetMaxResults(10)
.List();
The only problem is this example is in HQL, and I need to do the same thing in an ICriteria query. To achieve the equivalent with ICriteria, I need to do something like:
IList list = session.CreateCriteria<Blog>()
.SetFirstResult(5)
.SetMaxResults(10)
.SetProjection(Projections.RootEntity(), Projections.SqlFunction("rowcount", NHibernateUtil.Int64))
.List();
The problem is there is no such thing as Projections.RootEntity(). Is there any way to select the root entity as one of the projections in a projection list?
Yes, I know I could just use CriteriaTransform.TransformToRowCount() but that would require executing the query twice - once for the results and once for the row count. Using Futures may help a little by reducing it to one round-trip, but it's still executing the query twice on the SQL Server. For intensive queries this is unacceptable. I want to avoid the overhead, and return the row count and the results in the same query.
The basic question is: using ICriteria, is there any way to select the root entity AND some other projection at the same time?
EDIT: some related links:
https://nhibernate.jira.com/browse/NH-1372?jql=text%20~%20%22entity%20projection%22
https://nhibernate.jira.com/browse/NH-928
I implemented a RootEntityProjection. You can try the code, which you can find at: http://weblogs.asp.net/ricardoperes/archive/2014/03/06/custom-nhibernate-criteria-projections.aspx.
Let me know if it helped.

Doctrine - strange moved parenthesis in the query

I have tested and done quite some research online, but still no luck. Did anyone ever encounter this problem ?
Say, I have a doctrine query set up like:
$q = Doctrine_Query::create()
->update('PckFolder')
->set('id_path', "CONCAT(?, RIGHT(id_path, LENGTH(id_path)-?))", array($newPath, $lenOld))
->where("id_path like '$oldPath%'");
// and I print the query out
$qstr = $q->getSqlQuery(array($newPath, $lenOld));
Instead of giving me:
UPDATE pck_folder SET id_path = CONCAT(?, RIGHT(id_path, LENGTH(id_path)-?)) WHERE (id_path like '1/2//%')
Doctrine gave me:
UPDATE pck_folder SET id_path = CONCAT(?, RIGHT(id_path, LENGTH(id_path-?))) WHERE (id_path like '1/2//%')
please note this part RIGHT(id_path, LENGTH(id_path)-?)
(Note: I'm assuming you're using Doctrine 1.2. I haven't used Doctrine 2.0 yet.)
I had not encountered that specific bug before, but I have found numerous problems with the implementation of update() in Doctrine_Query. Essentially anything but the most very straightforward update queries will cause the parser to generate wrong or invalid queries. For example, it can't handle sub-selects within an update.
Try writing a Raw SQL query, or else use a less efficient but fully-functional workaround: Select the records you want to update using Doctrine_Query, then iterate over them and set the field in PHP, then call save() on each one.
By the way, there's a big GOTCHA inherent with use of UPDATE queries and Doctrine that sort of forces you to use that workaround in many cases anyway. That is, if you or your plugins have made use of the nifty Doctrine hook methods within your models but you execute a SQL-level update that affects those records, the hooks will get silently circumvented. Depending on your application, that may wreck your business logic processing.

Hibernate and dynamic SQL

do you know anything about Hibernate and its ability to generate dynamic sql queries with HQL?
I you have any links I would appreciate posting, I can't find nothing about it in Hibernate`s documentation.
Best regards
Gabe
//edit
so maybe I will precise what I mean. I am wondering if some HQL code generates SQL queries which uses something like EXECUTE (for postgres)
Not sure what you're aiming for here? HQL in Hibernate will always generate SQL, and you can put your HQL together differently based on input. It will always generate new SQL for each permutation and run. You can make Hibernate precompile/cache queries but that's just a performance optimization and shouldn't be your first concern.
I would also consider looking into the Criteria API which lets you stay a lot more object oriented instead of working with tons of strings.
If you're talking about static queries using dynamic arguments, the syntax is
select f from Foo f where f.bar = ? and f.zim = ?
or, with named parameters
select f from Foo f where f.bar = :bar and f.zim = :zim
If you're talking about completely dynamically created queries based on a set of criteria, then the API to use is... the Criteria API.
Both are largely covered in the Hibernate reference documentation.