QueryOver Many to Many Items - nhibernate

I have 2 entities, linked via a Many to Many called Parent and Child.
In Child I have an IList of Parents,
In Parent I have an IList of Childs.
I am trying to do a query on a list of parents, that is linked to a child.
Conceptually wise, I am looking for something like this:
var Query = session.QueryOver<Parent>()
Query.Where(o => o.Children.Contains(child));
But this won't work, so what ways can I get this to work?
Thanks!

You need to use JoinQueryOver
session.QueryOver<Parent>().JoinQueryOver<Child>(p => p.Childs)
.Where(c => c.Id == child.Id)

var query = session.QueryOver<Parent>()
.Where(o => o.Children.Contains(child));
or
var query = session.Query<Parent>()
.Where(o => o.Children.Contains(child));
or see Vadim

Related

Restrict fluent nhibernate queryover on multiple child entities comparing properties with a single value

I would like to restrict a query using the QueryOver mechanism in Fluent Nhibernat. I found that I can do this using WhereRestrictOn but there seems to be no possibility to compare to just one value. A IsEqual method of sorts.
I quick example might explain better what my issue is
class Parent{
IList<Child1> C1 {get;set;}
IList<Child2> C2 {get;set;}
}
class Child1{
int Id {get;set;}
}
class Child2{
int Id {get;set;}
}
//What I can do
var result = session.QueryOver<Parent>()
.WhereRestrictionOn(x => x.C1.Id).IsIn(new[]{3})
.AndRestrictionOn(x => x.C2.Id).IsIn(new[]{5}).List();
//What I would like to do
var result = session.QueryOver<Parent>()
.WhereRestrictionOn(x => x.C1.Id).IsEqual(3)
.AndRestrictionOn(x => x.C2.Id).IsEqual(5).List();
So basically my issue is that I'm not able to compare with one value but always have to artifically create an array. Is this not possible or am I missing something?
If it is possible please tell me how. If it is not possible I would appreciate an explantion as to why not.
Thanks in advance.
Try this:
Child1 c1Alias = null;
Child2 c2Alias = null;
var result = session.QueryOver<Parent>()
.InnerJoin(x => x.C1, () => c1Alias) // or use Left.JoinAlias
.InnerJoin(x => x.C2, () => c2Alias) // or use Left.JoinAlias
.Where(() => c1Alias.Id == 3)
.And(() => c2Alias.Id == 2)
.List();
I think you want a pair of Subqueries rather than a restriction, but you'll have to map the ParentID value in both Child1 and Child2.
Each SubQuery should return the ParentID where the childID is your search value, and then you can use a conjunction to return the Parent for both children, or null if there isn't one, I suppose.

Linq Many to many

Could anyone please help with the linq for this problem.
Users have a list of Properties and Properties have a list of Users.
I first do a query to get all Properties with a particular CompanyId. This makes a new list which we'll call MyProperties.
I need to get all Tenants that have a property in the MyProperties list.
For other reasons, I don't have access to the "PropertiesUsers" Join table.
Sorry if it looks like I haven't thought this through, I've been banging my head all day on it.
You can use Enumerable.SelectMany() to flatten the hierarchy:
var myProperties = dbContext.Properties.Where(property => property.CompanyId = companyId);
var tenants = myProperties.SelectMany(property => property.Tenants);
Use Intersect:
var myPropertyIds = MyProperties.Select(p => p.PropertyId).ToArray();
var result = Users.Where(u => myPropertyIds.Intersect(
u.Properties.Select(p => p.PropertyId))
.Any());
If you are sure that the properties in both lists are the same instances you could use
var result = Users.Where(u => MyProperties.Intersect(
u.Properties)
.Any());

Nhibernate query<T> / queryover<T> orderby a subquery

I am having issues getting Nhibernate 3.3.2.4000 to generate the correct subquery used in the orderby clause as displayed below:
select *
from dbo.Person p inner join dbo.Task t on p.Task_FK = p.TaskId
order by (select p.CustomerNumber where p.IsMain=1) desc
We have two entities: Task and Person
One task can have N persons related to it. I.e Task has an IList property.
How can I make Nhibernate generate the correct subquery ? I have gotten as far as something like this with the Query API:
query = query.OrderBy(x => x.Persons.Single(t => t.CustomerNumber));
but I am unsure how I can correctly generate the where clause as displayed in the original sql query. Is this perhaps easier done using the queryover api somehow?
Any advice or guidance is most welcome.
Task task = null
Person person = null;
var subquery = QueryOver.Of<Task>()
.Where(t => t.Id == task.Id)
.JoinQueryOver(t => t.Persons, () => person)
.Where(p => p.IsMain)
.Select(() => person.CustomerNumber);
var query = session.QueryOver(() => task)
.OrderBy(Projections.SubQuery(subquery))
.FetchMany(x => x.Persons)
return query.List();

QueryOver to select an entity

I have a question. I have this query:
var query = QueryOver.Of<Item>()
.JoinQueryOver<ItemRelation>(p => p.ItemRelation)
.Where(r => r.Item1.Id == itemId)
How can I return only Item entity but not Item Relation?
Thanks
The query actually should only return Predmet ... The RelacijaPredmeta is a property of it. If you don't want to load it, use lazy loading, or select the properties of Predmet individually.

NHibernate ICriteria - order by child collection count?

Here is a simple example scenario -
A 'Tag' has many 'Questions'. When I get a list of Tags how do I order by the Tags Question Count using the Criteria API?
I have done this before but haven't touched NH in about 4 months and have forgotten... projections maybe? help!!!
Thanks
Sat down with a fresh pair of eyes and figured it out... Tags are now ordered by a propery on the Tags Question collection (views).. which made alot more sence in my domain than ordering by the count of children
public IList<Tag> GetTop(int numberOfTags)
{
using (ITransaction transaction = Session.BeginTransaction())
{
DetachedCriteria detachedCriteria = DetachedCriteria.For<Tag>()
.CreateCriteria<Tag>(x => x.Questions)
.AddOrder<Question>(x => x.Views, Order.Desc)
.SetMaxResults(numberOfTags)
.SetProjection(Projections.Distinct(Projections.Id()));
IList<Tag> tags = Session.CreateCriteria<Tag>()
.SetFetchMode<Tag>(x => x.Questions,FetchMode.Join)
.Add(LambdaSubquery.Property<Tag>(x => x.Id).In(detachedCriteria))
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.List<Tag>();
transaction.Commit();
return tags;
}
}
Try:
var tags = Session.CreateCriteria(typeof(Tag))
.AddOrder(Order.Asc("Tag.Question.Id")
.List<Tag>();
// If that does not work, try:
var tags = Session.CreateCriteria(typeof(Tag))
.CreateCriteria("Question", "TagQuestion", JoinType.InnerJoin)
.AddOrder(Order.Asc("TagQuestion.Id")
.List<Tag>();
Ordering on joined columns.
Ordering the query criteria.
Edit: Unless you're deciding against it or your already comfortable with the Criteria API, you should take a look at either HQL or NHibernate.Linq:
var tags = Session.Linq<Tag>()
.OrderBy(tag => tag.Question.Id)
.ToList();
Linq to NHibernate: a vast improvement.