nhibernate queries SubQueryExpression - nhibernate

Can someone explain me what are NHibernate SubQueryExpression based queries. Any links with concrete examples are very welcome.
Thanks
Update:
Let's say that I have one entity named Beach. That beach can have many images. I want to select Beach entity and it;s first image from Images collection. I want to carry arround only that selected image object, or if I select only second object to carry only that object.
I do not want to access like Images.First() cause that will initialize all collection, if you need more info, plase ask.

var query = session.QueryOver(() => vehicleAlias)
.Left.JoinAlias(() => vehicleAlias.VehicleRegistrations, () => vehicleRegistrationAlias)
.WithSubquery.WhereProperty(() => vehicleRegistrationAlias.RegistrationExpiryDate).Eq(
QueryOver.Of(() => vehicleRegistrationAlias2)
.Where(() => vehicleRegistrationAlias2.Vehicle.Id == vehicleAlias.Id)
.Select(Projections.Max<VehicleRegistration>(ps => ps.RegistrationExpiryDate)));
query.Left.JoinAlias(() => vehicleRegistrationAlias.VehicleRegistrants, () => vehicleRegistrantAlias)
.Where(() => vehicleRegistrantAlias.Client.Id == clientId);
This is a subquery I just wrote for my work that took me a while to write. I don't really know what you are asking in specific but here is a sample. If you have any questions on it let me know.
.Select(Projections.Max(ps => ps.RegistrationExpiryDate))) This line does all the work in the sub query. It selects the most recent vehicle registration. Vehicle registration alias 2 is the object being queried as a sub query.
So this will pull back only the current vehicle registration for a vehicle. One vehicle may have many vehicle registrations. Its the .Select statement that can be modified into something like .OrderById.Desc.SelectTop(1) or something like that.
I hope this edit helps.

Related

NHibernate - why is this collection not initialized / eager fetched?

Considering this:
var pfs = Session.QueryOver<Pegfile>()
.JoinAlias(pf => pf.Responses, () => responseAlias)
.List();
followed by this
Debug.Print(pfs.First().Responses.Count.ToString());
Why would that debug statment make NHibernate go back and requery the Response collection, surely it was initialized in the first query?
You need to use Fetch to pre-load the collection:
var pfs = Session.QueryOver<Pegfile>()
.JoinAlias(pf => pf.Responses, () => responseAlias)
.Fetch(pf => pf.Responses).Eager
.List();
JoinAlias aliases the collection so that you can reference it in a where clause, etc.
I'm not sure about QueryOver but the LINQ provider also uses several optimizations that would cause the collection to not be loaded, such as issuing a SQL aggregate COUNT query when you invoke Count.
Gets me every single time, why don't i remember? The join has to be a Lefty - grr love and hate NH in equal measures.
var pfs = Session.QueryOver<Pegfile>()
.Left.JoinAlias(pf => pf.Responses, () => responseAlias)
.List();

RavenDB - Get IDs of root property within a non-root level property

With RavenDB, is it possible to get the IDs of a property within another property? For example, if Foo has a list of Bar objects, and each Bar object has a SnuhId property, can I use an Include that gets the IDs of each Snuh property?
I tried the query below, but I get a RavenDB exception: index out of range. In this query, ApplicationServer is a root element, and it has a list of ApplicationsWithOverrideGroup objects. Each of those objects has an ApplicationId property. It's the ApplicationId that I want to get in the include.
IEnumerable<ApplicationServer> appServers = QueryAndCacheEtags(session =>
session.Advanced.LuceneQuery<ApplicationServer>()
.Include(x => x.CustomVariableGroupIds)
// This is the line I'm trying to make work:
.Include(x => (from item in x.ApplicationsWithOverrideGroup select item.ApplicationId).ToList())
).Cast<ApplicationServer>();
Either of these approaches appears to be working. Need to thoroughly test.
.Include(x => x.ApplicationsWithOverrideGroup)
or
.Include(x => x.ApplicationsWithOverrideGroup[0].ApplicationId)
If that first option is indeed working, then a property, specified in an Include(), will include the ID properties within it. Is that right?
I'm not sure if both of those are really working, but they seem to be. If they both work, I wonder if one is better than the other...
Ok, that's NOT WORKING. The NumberOfRequests is increasing, which I'm guessing means the number of trips to the DB is increasing, instead of just what's in the session.
Ok, none of those suggestions worked in the question above. I think what has to be done is to include the IDs of the nested properties in the root object.
And that's what I did, and I was able to get the NumberOfRequests on the session object down to one. Curiously, I had to change this:
// Not using this, at least for now, because it increased the NumberOfRequests on the session...
appServer.CustomVariableGroups = new ObservableCollection<CustomVariableGroup>(
QueryAndCacheEtags(session => session.Load<CustomVariableGroup>(appServer.CustomVariableGroupIds)).Cast<CustomVariableGroup>());
To this:
// ... however, this kept the NumberOfRequests to just one. Not sure why the difference.
appServer.CustomVariableGroups = new ObservableCollection<CustomVariableGroup>();
foreach (string groupId in appServer.CustomVariableGroupIds)
{
appServer.CustomVariableGroups.Add(QuerySingleResultAndCacheEtag(session => session.Load<CustomVariableGroup>(groupId)) as CustomVariableGroup);
}

NHibernate Queryover - How do I return only a child collection

I am running into difficulty with the following nhibernate queryover query. I am probably over-complicating things, but here is the problem:
I have an entity named AuctionStatistic that links to an auction (this is uni-directional and I do not have links from auctions back to statistics)
I would like to query the statistic table, find all auction IDs and pull back only those that meet a certain threshold - i.e. top 500 auctions by views
Once I've gotten the top X (in this example i'm hardcoding to 10000 views) I want to pull back the auction id and name. For this particular query I don't need any of the data stored in the statistics table (though this is used elsewhere and is not redundant)
I figured I could use something like the following to get back just the auctions, but because I'm querying over AuctionStatistic it expects the selected value to be of type AuctionStatistic (or a list thereof)
var auctions = _session.QueryOver<AuctionStatistic>().Where(c => c.ViewCount > 10000).Fetch(x=>x.Auction).Eager.Select(x=>x.Auction);
Can anyone suggest a better way of doing this?
Thanks
JP
Without bi-directional this is probably your best bet.
Auction auctionAlias = null;
AuctionDTO dto = null;
var auctionDtos = _session.QueryOver<AuctionStatistic>()
.Where(c => c.ViewCount > 10000)
.JoinAlias(x => x.Auction, () => auctionAlias)
.SelectList(list => list
.Select(() => auctionAlias.id).WithAlias(() => dto.id)
.Select(() => auctionAlias.name).WithAlias(() => dto.name))
.TransformUsing(Transformers.AliasToBean<AuctionDTO>())
.List<AuctionDTO>();

Finding user that have at least one tag object in linq?

I have an object User.
User 1..N Tags(string).
For instance, i have a List of Tag object. How can i query the User to find all the user that have at least 1 Tag in side the list of tags?
Thanks in advance :)
Assuming your code snippet means you have a property Tags of type Foo<string> where Foo is some sequence type, you could just use:
var taggedUsers = users.Where(user => tags.Any(tag => user.Tags.Contains(tag));
(Actually, that's assuming you have a list of strings as Tags - the question is somewhat unclear. However, hopefully it'll be enough to sort you out.)
EDIT: Okay, with the details in the comments, I think you probably just need:
var taggedUsers = users.Where(user => tags.Any(tag => user.Tags
.Select(t => t.Value)
.Contains(tag));

NHibernate Eager Loading with Queryover API on a complex object graph

I've got a pretty complex object graph that I want to load in one fell
swoop.
Samples have Daylogs which have Daylog Tests which have Daylog
Results
Daylog Tests have Testkeys, Daylog Results have Resultkeys, and
TestKeys have Resultkeys.
I'm using the QueryOver API and Future to run these all as one query,
and all the data that NHibernate should need to instantiate the entire
graph IS being returned, verfied by NHProf.
public static IList<Daylog> DatablockLoad(Isession sess,
ICollection<int> ids)
{
var daylogQuery = sess.QueryOver<Daylog>()
.WhereRestrictionOn(dl => dl.DaylogID).IsIn(ids.ToArray())
.Fetch(dl => dl.Tests).Eager
.TransformUsing(Transformers.DistinctRootEntity)
.Future<Daylog>();
sess.QueryOver<DaylogTest>()
.WhereRestrictionOn(dlt =>
dlt.Daylog.DaylogID).IsIn(ids.ToArray())
.Fetch(dlt => dlt.Results).Eager
.Inner.JoinQueryOver<TestKey>(dlt => dlt.TestKey)
.Fetch(dlt => dlt.TestKey).Eager
.Inner.JoinQueryOver<ResultKey>(tk => tk.Results)
.Fetch(dlt => dlt.TestKey.Results).Eager
.Future<DaylogTest>();
sess.QueryOver<DaylogResult>()
.Inner.JoinQueryOver(dlr => dlr.DaylogTest)
.WhereRestrictionOn(dlt =>
dlt.Daylog.DaylogID).IsIn(ids.ToArray())
.Fetch(dlr => dlr.ResultKey).Eager
.Fetch(dlr => dlr.History).Eager
.Future<DaylogResult>();
var daylogs = daylogQuery.ToList();
return daylogs;
}
However, I still end up with proxies to represent the relationship
between Testkey and ResultKey, even though I'm specifically loading
that relationship.
I think this entire query is probably representative of a poor
understanding of the QueryOver API, so I would like any and all advice
on it, but primarily, I'd like to understand why I get a proxy and not
a list of results when later I try to get
daylogresult.resultkey.testkey.results.
Any help?
The answer was to call NHibernateUtil.Initialize on the various objects. Simply pulling the data down does not mean that NHibernate will hydrate all the proxies.
You have to load all your entities in one QueryOver clause to get rid of proxies. But in this case you will have a lot of joins in your query, so I recommend to use lazy loading with batching.