Does NHibernate support subqueries in the from clause? For example I have sql queries looking like this:
SELECT subquery.Id, sum(subquery.Value) ...
FROM (SELECT DISTINCT Id, Value, ... FROM table1) as subquery
WHERE ...
GROUP BY subquery.Id
I've only found this info:
HQL does not have subquery in from clause support. I've been consider
how to add this, but I think it's going to be a substantial effort.
It's coming, but unless somebody can provide more development time,
it's going to take while to implement.
Patrick Earl
from Google Groups (17.08.2011). Is it still relevant? Maybe I can use Linq to NHibernate?
If this functionality is not provided you could create a database view that does this and map your nhibernate entity to the database view.
Related
Recently, I need to use JPA in my project.
However, I encountered some difficulties. JPA seemes to be harder than I thought.
So, I post my problem here, hoping that, some guys may help me.
There are two tables operation and analysis, the sql is like the following:
select op_id from operation where flag = 1
union
select an_id from analysis where on_type = "processed";
op_id and an_id are two column names actually means the same.
Can anyone help me writing a JPA version of this?
I'm very grateful of that.
Thank you very much.
JPQL does not support unions.
You have four options:
You can create a View in your DB that would do the unioning, then map to that view
Write a native SQL that does the union (since you only need the ID, this is a valid option)
If the IDs are distinct, you can run two queries, and concatenate the result list (if not distinct, you could use Sets to filter duplications)
If you are using the latest (at least >=2.4) EclipseLink as a JPA provider, you can use UNION
See this question here.
Is there any way to get NHibernate to use a Window function?
Specifically, I'm looking to create a query like the following:
SELECT
date,
SUM(Price) OVER (ORDER BY date)
FROM purchases
GROUP BY date
I've Search the web and can't find anything about window functions and NHibernate
Specifically, I'm using the QueryOver interface for NHibernate.
If it's not possible, what other solutions are there to keep database independence in my code?
Good question but unfortunately I've never seen any code within NHibernate itself that would allow it to generate such a window function.
Your only option would be to use a named query. In your named query you could either type out the SQL by hand or call a stored procedure.
You stated that you wanted to keep your solution database independent. I've never personally cared much doing such as thing as I always work with SQL Server but I can understand where you're coming from. I've heard of several people who run their integration tests with an in memory SQLite solution and then run their actual code on SQL Server or Oracle.
In your scenario, I don't believe the SQL in your question is ANSI compliant anyway so you'd have to re-write it in a different way unfortunately if you used a named query to make it database independent.
As far as I know, you can't do that with the QueryOver API.
What I would do to keep as DB independant as possible would be to consider the windowed query as a join between your table and a group by query. Then to write a QueryOver which would lead this join.
Considering you query it would lead to this : (though the example does not seem to really show the need for a windowed query)
SELECT
purchases.date,
purchasesGroup.priceSum
FROM
purchases
INNER JOIN
(SELECT date, SUM(Price) as priceSum FROM purchases GROUP BY date)
AS purchasesGroup
on purchases.date = purchasesGroup.date
You could potentially use a view for this. That could at least abstract away a little bit of it, although you are really migrating the dependency to the database schema.
I've run into this kind of issue as well lately, and I'm starting to realize that I am often trying to use NHibernate in a way that isn't really about persisting entities. If I were Ayende Rahien I would probably know what to do, but since I am not I usually end up mixing in a little Dapper when I just need something like a read-only aggregate result such as statistics about data.
When looking at our queries from NHibernate it's clear that the column alias is not consistent, that a problem for performance when the sql server execution plan seeing the same query as different query's because of the inconsistent column alias.
An example could be something like this:
SELECT this_.Id as Id44_0_ FROM dbo.[Foos] this_
SELECT this_.Id as Id43_0_ FROM dbo.[Foos] this_
Is there any way we can make consistent column alias?
We are using Fluent NHibernate with Auto mapping
Optionally by setting projection you can get a custom name as an alias in the query as follows
Projections.Property("candidate.Name"), "CandidateName");
How to use NHibernate Projections to retrieve a collection
I never seen same NH query to generate different SQL while your application is running.
I think you don't need to worry about performance because of this. (Except of the case when you need to start and stop you app frequently.)
Any changes you need to make SQL queries consistent all the time (even after you data model changes) are painful, not absolutely good solutions and I think not acceptable for you.
I have a very silly doubt in NHibernate. There are two or three entities of which two are related and one is not related to other two entities. I have to fetch some selected columns from these three tables by joining them. Is it a good idea to use session.CreateSql() or we have to use session.CreateCriteria(). I am really confused here as I could not write the Criteria queries here and forced to use CreateSql. Please advise.
in general you should avoid writing SQL whenever possible;
one of the advantages of using an ORM is that it's implementation-agnostic.
that means that you don't know (and don't care) what the underlying database is, and you can actually switch DB providers or tweak with the DB structure very easily.
If you write your own SQL statements you run the risk of them not working on other providers, and also you have to maintain them yourself (for example- if you change the name of the underlying column for the Id property from 'Id' to 'Employee_Id', you'd have to change your SQL query, whereas with Criteria no change would be necessary).
Having said that- there's nothing stopping you from writing a Criteria / HQL that pulls data from more than one table. for example (with HQL):
select emp.Id, dep.Name, po.Id
from Employee emp, Department dep, Posts po
where emp.Name like 'snake' //etc...
There are multiple ways to make queries with NH.
HQL, the classic way, a powerful object oriented query language. Disadvantage: appears in strings in the code (actually: there is no editor support).
Criteria, a classic way to create dynamic queries without string manipulations. Disadvantages: not as powerful as HQL and not as typesafe as its successors.
QueryOver, a successor of Criteria, which has a nicer syntax and is more type safe.
LINQ, now based on HQL, is more integrated then HQL and typesafe and generally a matter of taste.
SQL as a fallback for cases where you need something you can't get the object oriented way.
I would recommend HQL or LINQ for regular queries, QueryOver (resp. Criteria) for dynamic queries and SQL only if there isn't any other way.
To answer your specific problem, which I don't know: If all information you need for the query is available in the object oriented model, you should be able to solve it by the use of HQL.
The title pretty much says it all. Under "standard-compliant" SQL I mean SQL constructs allowed in any of SQL standards.
I looked through the "Understanding SQL" book, but it mentions subqueries only inside WHERE, GROUP BY, HAVING etc. clauses, not SELECT and FROM (or maybe I'm missing something).
I know MS SQL allows sub-SELECT's in SELECT and FROM. I would like to know if it is a standard behavior. Or maybe it isn't standard, but is now implemented in major SQL databases (I have very little experience with DB's other than MS SQL)?
Yes. You can use a subquery as a derived table wherever you can use a table in a select statement.
SQL ANSI 92