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"
Related
I have a number of database table that looks like this:
EntityId int : 1
Countries1: "1,2,3,4,5"
Countries2: "7,9,10,22"
I would like to have NHibernate load the Country entities identifed as 1,2,3,4,5,7,9 etc. whenever my EntityId is loaded.
The reason for this is that we want to avoid a proliferation of joins, as there are scores of these collections.
Does fetching the countries have to happen as the entity is loaded - it is acceptable that you run a query to fetch these? (You could amend your DAO to run the query after fetching the entity.) The reason I ask is that simply running a query compared to having custom code invoked when entities are loaded requires less "plumbing" and framework innards.
After fecthing your entity, and you have the Country1,Country2 lists, You can run a query like:
select c from Country c where c.id in (:Country1)
passing :Country1 as a named parameter. You culd also retrieve all rows for both sets of countries
select Entity e where e.id in (:Country1, :Country2)
I'm hoping the country1 & country2 strings can be used as they are, but I have a feeling this won't work. If so, you should convert the Strings to a collection of Integers and pass the collection as the query parameter.
EDIT: The "plumbing" to make this more transparent comes in the form of the IInterceptor interface. This allows you to plug in to how entities are loaded, saved, updated, flushed etc. Your entity will look something like this
class MyEntity
{
IList<Country> Country1;
IList<Country> Country2;
// with public getter/setters
String Country1IDs;
String Country2IDs;
// protected getter and setter for NHibernate
}
Although the domain object has two representations of the list - the actual entities, and the list of IDs, this is the same intrusion that you have when declaring a regular ID field in an entity. The collections (country1 and Country2) are not persisted in the mapping file.
With this in place, you provide an IInterceptor implementation that hooks the loading and saving. On loading, you fetch the value of the countryXID property an use to load the list of countries (as I described above.) On saving, you turn the IList of countries into an ID list, and save this value.
I couldn't find the documentation for IInterceptor, but there are many projects on the net using it. The interface is described in this article.
No you cannot, at least not with default functionality.
Considering that there is no SPLIT string function in SQL it would be hard for any ORM to detect the discreet integer values delimited by commas in a varchar column. If you somehow (custom sql func) overcame that obstacle, your best shot would be to use some kind of component/custom user type that would still make a smorgasbond of joins on the 'Country' table to fetch, in the end, a collection of country entities...
...but I'm not sure it can be done, and it would also mean writing from scratch the persistence mechanism as well.
As a side note, I must say that i don't understand the design decision; you denormalized the db and, well, since when joins are bad?
Also, the other given answer will solve your problem without re-designing your database, and without writing a lot of experimental plumbing code. However, it will not answer your question for hydration of the country entities
UPDATE:
on a second thought, you can cheat, at least for the select part.
You could make a VIEW the would split the values and display them as separate rows:
Entity-Country1 View:
EntityId Country
1 1
1 2
1 3
etc
Entity-Country2 View:
EntityId Country
1 7
1 9
1 10
etc
Then you can map the view
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.
I am trying to efficiently work with parent & child (post & tags) entities. A sample of the code can be seen here: http://gist.github.com/297464
Using the following results in less than 10 distinct Post entities if any of Post contains more than 1 tag.
var posts = session
.CreateCriteria<Post>()
.SetMaxResults(10)
.SetFetchMode("Tags", FetchMode.Eager)
.List<Post>();
If I remove the .SetFetchMode line above, I get the 10 records I am looking for, but all of the Tag entities are queried and then filtered in memory.
It seems like I should be able to instruct NHiberate to either pass in a list of PostIds or do a join.
I am pretty new to NHiberate so it is also entirely possible I am going at this completely wrong.
Thanks,
Scott
The problem is that SetMaxResults is not applied to the number of root entities returned from the query, it is translated into a T-SQL TOP (in the case of SqlServer), which is applied to the result from a join query. Since there is one row in the result set for each child of a root entity the TOP will not have the desired effect.
To achieve a limit on the number of root entities you could use a join query with a subquery that contains the SetMaxResults limit.
// Select the ids of the first ten posts
var subquery = DetachedCriteria.For<Post>()
.SetMaxResults(10)
.SetProjection(Projections.Property("Id"));
// Do a join query with posts and tags, for the posts who's ids are
// in the result of the subquery
var posts = session.CreateCriteria<Post>()
.SetFetchMode("Tags", FetchMode.Join)
.Add(Subqueries.PropertyIn("Id", subquery))
.SetResultTransformer(Transformers.DistinctRootEntity)
.List<Post>();
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.
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.