(N)Hibernate Auto-Join - sql

I'm developing a web- application using NHibernate. Can you tell me how to write a NHibernate Query for the following SQL query:
SELECT v1.Id
FROM VIEW v1
LEFT JOIN VIEW v2 ON v1.SourceView = v2.Id
ORDER BY v1.Position
It's basically a auto-join but I don't know how to write this in Nhibernate. Lets say the property names are the same as the table column names.

You could just perform the select on the original entity and make the association between the two objects "lazy = false". As long as the entities are mapped then both will be returned and you wont get a lazyloadingexception when trying to access the object.
If you don't want to map "lazy=false" then you can also iterate through the results and perform some sort of operation (such as asking if it is null; if(v1.AssocatedObject == null){}) to ensure the data is loaded while the session is open.
Update:
I think there is actually a better one than that in, NHibernateUtil.Initialise() that can initialise a collection without having to wander through it.

Related

NHibernate: Combining result transformers?

I'm working with the criteria API, querying against a mapping file that I cannot really change. There is a root entity with many child entities joined to it and certain queries have required us to add
criteria.SetResultTransformer(CriteriaSpecification.DistinctRootEntity);
in order to avoid getting duplicate entities when there are multiple SQL result-lines due to the joins. The problem is that now I also want to apply an alias-to-bean transformer, like so:
criteria.SetResultTransformer(Transformers.AliasToBean(typeof(MyDto)));
Using either one of these works great. However, I need to combine them: I want to load only the required columns into a DTO object, and also get only distinct root entities. How can I do this?
To load only required column into DTO you can use projection with DistinctEntityRootTransformer as follows
ICriteria criteria = session.CreateCriteria(typeof(YourEntity));
criteria.SetProjection(
Projections.Distinct(Projections.ProjectionList()
.Add(Projections.Alias(Projections.Property("Property"), "Property")));
criteria.SetResultTransformer(
new NHibernate.Transform.AliasToBeanResultTransformer(typeof(MyDto)));
IList list = criteria.List();

Nhibernate left join with 'with' still pulling back all child objects

I have the following hql:
Select q FROM GeneralQuestion q
Left Join q.QuestionResponses as qr with qr.ContactUid = :contactuid
WHERE q.ParentUid = :audituid
Obviously GeneralQuestion contains a collection of QuestionResponse objects. I have used the with keyword which I thought would limit the QuestionResponse objects returned to only those QuestionRespone objects with that specific contactuid.
The problem is that each GeneralQuestion stil contains all the QuestionResponses.
Is there a way to limit the QuestionResponse objects returned to be only of that contactuid?
I thought this was the whole point of with and I am now confused.
If you look at the executed SQL, it's probably retrieving just the filtered records when querying, then lazily reloading the collection when using it.
This makes sense, as NH has to track their state.
What you need to do is retrieve QuestionResponse instances directly in your select list, and that will be your "filtered collection"

How can one fetch partial objects in NHibernate?

I have an object O with 2 fields - A and B. How can I fetch O from the database so that only the field A is fetched?
Of course, my real application has objects with many more fields, but two fields are enough to understand the principal.
I am using NHibernate 2.1.
Thanks.
EDIT:
I wish to clarify. I need to fetch objects of type O. Sometimes I will want to fetch complete objects - meaning both A and B fields are set from the database values. But on other occasions, I would like to fetch O objects with just the A field set from the database values.
Use a projection to narrow the result set to the desired column(s) and a result transformer to convert the result into the type that you want.
This will return transient objects rather than persistent entities.
// select some User objects with only the Username property set
var u = session.CreateCriteria<User>()
.SetProjection( Projections.ProjectionList().Add(Projections.Property("Username"), "Username") )
.SetResultTransformer( Transformers.AliasToBean<User>() )
.List<User>();
HQL has a select new construct, which allows you to fetch only a subset of fields. Objects returned, however, cannot be saved back to the DB.
As an alternative, you can create additional classes with a limited set of properties an map those onto table in question.

nhibernate: how to map aggregates

Good afternoon, I'm trying to learn nHibernate and it's not terribly clear.
I need to get the result of an sql query:
select patient.name,
discipline.description,
sum(patient.enddate - patient.startdate) as totaltime
from treatment
join patient on patient.id = treatment.patientId
join discipline.id = treatment.disciplineId
I don't need to persist the result, just display it.
If I use hql directly:
What objects will it instantiate and return to me? Will it dynamically build a list of objects containing fields identical to the columns in the result set? The docs leave out this information.
If I need to make a mapping:
Do you create a mapping to a 'meta' object or to one of the joined tables (say 'treatment')?
Thanks
This can be achieved by using DTO objects ("data transfer objects"). You create an object that contains only the data you wish to return. Add an initializing constructor. Then your hql can be of the form:
select new mydto( x.value, y.value ) from x join x.y;
It doesn't seem to like using aggregate functions in the object constructor though.

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 :-)