HQL size using QueryOver without subquery - nhibernate

Hope that someone can answer this.
I know that I can do the following using hql (pseudo code below)
var hql = "from objectA l where size(l.ChildCollection) > 0";
var data = Session.CreateQuery(hql)
.List<objectA>();
Is there a wondering if you could do something similar using QueryOver. Without resorting to using a sub query.I have a session filter on ChildCollection.
Unfortunately,
var query = QueryOver.Of<ObjectA>()
.WhereRestrictionOn(x => x.ChildCollection).IsNotEmpty();
Produces,
WHERE
exists(
select
1
from
[ChildCollection]
where
this_.Id=ObjectA_Id
);
Where as the Hql produces,
where
(
select
count(childcollection1_.ObjectA_Id)
from
[ChildCollection] childcollection1_
where
objectA0_.Id=childcollection1_.ObjectA_Id
and childcollection1_.DTCreated between #p0 and #p1
)>0
Cheers
Tanzy

var query = QueryOver.Of<ObjectA>().WhereRestrictionOn(x => x.ChildCollection).IsNotEmpty();
Both queries will generate similar sql:
SELECT this_.Id
FROM [ObjectA] this_
WHERE exists(select 1 from [ChildObjectB] where this_.Id = [key])
Is this what you were trying to achieve?

Related

HQL syntax error : 'NHibernate.Hql.Ast.ANTLR.QuerySyntaxException'

As a beginner in HQL , I have a SQL query that I'm trying to transform into hql.
select * from (
   select *
   from CORRELATION_VUE
   where film = v_oldidfilm and FILM2 not in (
                           select c.idfilm
                           from cotes c
                           where idclient = v_idclient)
   order by CORRELATION desc
 
 )
 where rownum <= 3;
So in HQL I'm trying this :
ISession s = NHibernateHelper.GetCurrentSession();
ITransaction tx = s.BeginTransaction();
IQuery query = s.CreateQuery(
#"select u from (
select u from vueCorreliser u
where u.film = :idfilm
and u.FILM2 not in (
select c.idfilm from cote c
where c.idclient = :idclient)
order by u.CORRELATION desc)
where rownum <= 3; ")
.SetInt32("idfilm", idfilm)
.SetInt32("idclient", idclient);
IList<Film> result = query.List<Film>();
tx.Commit();
return result;
But I'm receiving a syntax error on the CreateQuery line.
What did I do wrong?
Thank you
Though I consider this a duplicate of this other question from you, here is a separate, more explicit answer here.
hql does not support sub-queries in from statement. (It supports them in other statements, such as in where conditions.) You have to rewrite your query without the sub-query in the from.
Your sub-query seems to be there only for limiting rows count. Remove the row limit from the query, and use .SetMaxResults(yourMaxRowCount) on the HQL query object instead.
There are no needs for the termination statement ; in HQL, and I do not know if it is supported. I think it is not, better remove it.
var query = s.CreateQuery(
#"select u from vueCorreliser u
where u.film = :idfilm
and u.FILM2 not in (
select c.idfilm from cote c
where c.idclient = :idclient)
order by u.CORRELATION desc")
.SetInt32("idfilm", idfilm)
.SetInt32("idclient", idclient)
.SetMaxResults(4);
That should fix the QuerySyntaxException.
By the way, your usage pattern of transaction is not safe. When using locally scoped transactions, always nest them in using for ensuring they are properly closed.
using (var tx = session.BeginTransaction())
{
...
tx.Commit();
return result;
}
Even in case of failure, the transaction will then always be disposed, which causes it to rollback if it were still ongoing.

Entity Framework, why is this sql being generated?

When I look at the SQL query generated by EF I see
SELECT [extent1].ID as ID,
[extent1].Name as Name
From(
Select myview.ID as ID,
myview.Name as Name
From myview) AS [extent1]
Where([Extent1].ID = #p_linq_0)
Why is the outside select happening on the inside select? I've got a very large table that I can get a record from easily with the outside query but the whole query combined times out.
My Linq query
var result = from i in invitationEntity.Invitations
.Where(a=>a.id == inviationId)
select i;
I am using SQL 2012 & EF5 & Linq.
Is there a way to "force" the simpler query?
Because you are calling "SELECT" once again at the end along with LINQ method.
var result = from i in invitationEntity.Invitations
.Where(a=>a.id == inviationId)
select i;
The last line select i, is useless, but EF is not aware of it whether it has anything useful or not, you can simply avoid it.
var result = invitationEntity.Invitations
.Where(a=>a.id == inviationId);
You can still enumerate result and get everything.
Ok sorry, I forgot to add, you don't have to use "from", you can simply use .Where(expression )
And if you want to use LINQ keywords, then you can use it this way,
var result = from i in invitationEntity.Invitations
where i.id == invitationId
select i;
You cannot mix LINQ keywords and LINQ extension methods.
i would say that
var result = from i in invitationEntity.Invitations
.Where(a=>a.id == inviationId)
select i;
this
a=>a.id == inviationId
from a=> generate
Select myview.ID as ID,
myview.Name as Name
From myview
so a is [extent1]
you should use a "standard" where clause
from i in invitationEntity.Invitations
where i.id == inviationId
select i;

NHibernate Criteria generate invalid SQL for Sybase when using Subqueries

the criteria:
var subQuery = DetachedCriteria.For<RecordInfo>();
.Add(Restrictions.Eq("Property1", "some string"))
.Add(Restrictions.EqProperty("Property2", "record.Id"))
.SetProjection(Projections.Max("Id"));
var criteria = session.CreateCriteria(typeof(Record), "record")
.CreateAlias("record.ListOfRecordInfo", "recordInfo")
.Add(Subqueries.PropertyEq("recordInfo.Id", subQuery));
will generate something like this for Sybase ASE 15.5 dialect:
SELECT this_.Record_Id as Record1_2_3
...
FROM Record this_
INNER JOIN Record_Info Record_Info_
ON this_.Record_Id = Record_Info_.Property_2
WHERE Record_Info_.Record_Info_Id =
(
SELECT max(this_0_.Record_Info_Id) as y0_
FROM Record_Info this_0_
WHERE this_0_.Property_1 = #p0
AND this_0_.Property_2 = this_.Record_Id
)
The problem is the as y0_ that was generated, Sybase doesn't allow alias for sub query for the version of Sybase I'm using.
How do I modify my queries so that NHibernate doesn't generate the alias for the sub query?
We can adjust the projection of the subquery with custom SQL statement. So instead of:
var subQuery = DetachedCriteria.For<RecordInfo>();
...
.SetProjection(Projections.Max("Id")); // instead of this
we can do this:
var subQuery = DetachedCriteria.For<RecordInfo>();
...
.SetProjection(Projections.SqlProjection(" MAX(RecordInfoId) " // use this
, new string[] {"ID"}
, new IType[] {NHibernate.NHibernateUtil.Int32}));
We have to use the column name, because we are skipping the NHibernate Property-to-Column (Id to RecordInfoId).
This will avoid the
SELECT max(this_0_.Record_Info_Id) as y0_ replacing it with
SELECT MAX(RecordInfoId) (our custom SQL)

Converting SQL script to LINQ with IN clause

I am trying to work out how to covert the script below from SQL in to LINQ. Any help would be welcome.
SELECT *
FROM
[tableName]
WHERE
[MyDate] IN
(SELECT
MAX([MyDate])
FROM
[tableName]
GROUP BY
[MyID])
I can't find an equivalent for the "IN" clause section. There are existing questions on this forum but none that cover selecting a DateTime.
Thanks in advance.
You can use the ".Contains(..)" function:
e.g.
var itemQuery = from cartItems in db.SalesOrderDetails
where cartItems.SalesOrderID == 75144
select cartItems.ProductID;
var myProducts = from p in db.Products
where itemQuery.Contains(p.ProductID)
select p;
Although it looks like 2 round trips, as the LINQ only constructs the query when the IEnumerable is tripped, you should get reasonable performance.
I think Any() is what you are looking for:
var result = tableName.Where(x =>
(from t in tableName
group t by t.MyID into g
where g.Max(y => y.MyDate) == x.MyDate
select 1).Any())

Using Hibernate's Criteria and Projections to Select Multiple Distinct Columns

Using Hibernate's Criteria, I want to execute the equivalent of:
select distinct uspscity, state from citycomplete where USPSCITY = 'HOUSTON'
I thought doing the following would yield the results I wanted:
ProjectionList projList = new ProjectionList();
projList.add(Projections.distinct(Projections.property("id.state")));
projList.add(Projections.distinct(Projections.property("id.uspsCity")));
criteria.setProjection(projList);
But, what this actually does is execute something like:
select distinct uspscity, distinct state from citycomplete where USPSCITY = 'HOUSTON'
Which throws an error, obviously.
Other than not using Criteria, is there a solution for this?
Thanks,
Brandon
ProjectionList projList = Projections.projectionList();
projList.add(Projections.property("id.state"));
projList.add(Projections.property("id.uspsCity"));
criteria.setProjection(Projections.distinct(projList));