In NHibernate, can I have a criteria query return a list of one property instead of a list of objects? - nhibernate

I'm a bit green with the criteria api. So far, I've been able to get a list of nhibernate objects by using .List().ToList() on an ICriteria object.
I was just wondering if it was possible, say, to get a list of ints of all the ID #s of the objects that would have been returned, instead of returning the objects.
I know you can do this with HQL but I'm searching the database with dynamic lists from the user gui so the criteria api seems to be the better option.
Thanks.
Isaac

You can use Projections to return only a subset of the properties of an object.

Related

NHibernate restriction Count of child collection

Take for example: a Person that has a collection of Pets. I want to only list the Persons that have at least 5 pets.
I have tried:
var result = (from a in UnitOfWork.CurrentSession.QueryOver<Person>()
where a.Pets.Count >4
select a
).List()
But it says it does not recognize the property Count (which makes sense because it is not a DB field). I also tried Count() and it still doesn't work saying it doesn't understand that function (throws exception).
I've tried all kinds of subqueries and criteria methods but I don't know enough to put it all together. And I don't know whether I shold use LINQ or HQL or QueryOver or Criteria...It would be much much mch easier in SQL but I don't want to "cheat"
I have been searching google like crazy, and everything I found either does not compile or I get a runtime error
You are using QueryOver instead of LINQ (Query<T>() extension method)

nHibernate abstractCriterion and making dynamically query

What i need to do is make query in nHibernate (fully dynamically i don't know how many objects i will have).
What this query should returns are objects of specific Ids(i got List<int>).
Is there any way to make restriction like
Restrictions.Eq("Id",first item from my list of ints).Or("Id",second item) .... and so on.
I know i can make it with AbstractCriterion but have no idea how to check if object from my List<int> is first one.
So how can I make that?
Thanks for advance:)
You need the In criteria:
session.CreateCriteria(typeof(XYZ))
.Add(Expression.In("Id", values))

Mongoid query in Rails: Can I find only those records which have embedded child objects?

I would like to write a query in a Rails model using mongoid, and I'd like it to return only those records which have embedded child objects (in this case, client work links).
I only want to find clients which have embedded client work links.
This is what I'd like, though obviously it doesn't work because of the "where" parameters.
def self.latest_client_press
Work.where("!self.work_links.empty?").desc(:updated_at).limit(4)
end
While it is possible in MongoDB to query on array's size, this feature is rather limited.
What people do instead (and what is recommended on that page) is store array length along with the array itself. This way you can index this field and query documents very efficiently.

NHibernate Projection using SqlQuery

I'm trying to reproduce the HqlQuery style 'select new ObjectToProjectOut' functionality. i.e. take a list of columns returned from a query and return as a list of ObjectToProjectOut types that are instantiated using a Constructor with as many parameters as the columns in the query.
This is in effect what 'select new ObjectToProjectOut' achieves in Hql.... but clearly that's not available in SqlQuery. I think I need to set a result transform and use either PassThroughResultTransformer, DistinctRootEntityResultTransformer etc to get it to work.
Anyone know what I should use ?
ok.... after looking at the NHibernate code it seems that I was looking for AliasToBeanConstructorResultTransformer.... of course!
However I may have found an nHibernate bug. If you have the same column name returned twice from two different tables (market.name and account.name, say) then by the time nHibernate returns the array from the db to the transformer, the first occurance of 'Name' will be used for both. Nasty.
Work around is to uniquely alias. With Hql, the sql generated is heavily aliased, so this is only a bug with SqlQuery.
Grrrr. Today must be my day, also found another nHibernate bug/issue I've posted to StackOverflow for comment.
You could use the AddEntity method to fill entities from a SQL query.
Here are two examples from the NHibernate docs:
sess.CreateSQLQuery("SELECT * FROM CATS")
.AddEntity(typeof(Cat));
sess.CreateSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS")
.AddEntity(typeof(Cat));

nhibernate and DDD suggestion

I am fairly new to nHibernate and DDD, so please bear with me.
I have a requirement to create a new report from my SQL table. The report is read-only and will be bound to a GridView control in an ASP.NET application.
The report contains the following fields Style, Color, Size, LAQty, MTLQty, Status.
I have the entities for Style, Color and Size, which I use in other asp.net pages. I use them via repositories. I am not sure If should use the same entities for my report or not. If I use them, where I am supposed to map the Qty and Status fields?
If I should not use the same entities, should I create a new class for the report?
As said I am new to this and just trying to learn and code properly.
Thank you
For reports its usually easier to use plain values or special DTO's. Of course you can query for the entity that references all the information, but to put it into the list (eg. using databinding) it's handier to have a single class that contains all the values plain.
To get more specific solutions as the few bellow you need to tell us a little about your domain model. How does the class model look like?
generally, you have at least three options to get "plain" values form the database using NHibernate.
Write HQL that returns an array of values
For instance:
select e1.Style, e1.Color, e1.Size, e2.LAQty, e2.MTLQty
from entity1 inner join entity2
where (some condition)
the result will be a list of object[]. Every item in the list is a row, every item in the object[] is a column. This is quite like sql, but on a higher level (you describe the query on entity level) and is database independent.
Or you create a DTO (data transfer object) only to hold one row of the result:
select new ReportDto(e1.Style, e1.Color, e1.Size, e2.LAQty, e2.MTLQty)
from entity1 inner join entity2
where (some condition)
ReportDto need to implement a constructor that has all this arguments. The result is a list of ReportDto.
Or you use CriteriaAPI (recommended)
session.CreateCriteria(typeof(Entity1), "e1")
.CreateCriteria(typeof(Entity2), "e2")
.Add( /* some condition */ )
.Add(Projections.Property("e1.Style", "Style"))
.Add(Projections.Property("e1.Color", "Color"))
.Add(Projections.Property("e1.Size", "Size"))
.Add(Projections.Property("e2.LAQty", "LAQty"))
.Add(Projections.Property("e2.MTLQty", "MTLQty"))
.SetResultTransformer(AliasToBean(typeof(ReportDto)))
.List<ReportDto>();
The ReportDto needs to have a proeprty with the name of each alias "Style", "Color" etc. The output is a list of ReportDto.
I'm not schooled in DDD exactly, but I've always modeled my nouns as types and I'm surprised the report itself is an entity. DDD or not, I wouldn't do that, rather I'd have my reports reflect the results of a query, in which quantity is presumably count(*) or sum(lineItem.quantity) and status is also calculated (perhaps, in the page).
You haven't described your domain, but there is a clue on those column headings that you may be doing a pivot over the data to create LAQty, MTLQty which you'll find hard to do in nHibernate as its designed for OLTP and does not even do UNION last I checked. That said, there is nothing wrong with abusing HQL (Hibernate Query Language) for doing lightweight reporting, as long as you understand you are abusing it.
I see Stefan has done a grand job of describing the syntax for that, so I'll stop there :-)