I have a table Team and I have a table Location. Each team can have multiple locations and each location could have multiple teams, so it is a many to many relationship.
When this scenario is created in the database, there will be 3 tables, Team, Location and TeamLocation to hold the many to many links.
I have mapped this in nhibernate using the following... Team.hbm.xml
<class name="App.Data.Entities.Team,App.Data.Entities" table="`Team`" lazy="true">
<id name="Teamid" column="`TeamID`" type="Guid">
<generator class="assigned" />
</id>
<property type="string" not-null="true" length="250" name="TeamName" column="`TeamName`" />
<bag name="TeamLocations" inverse="false" table="`TeamLocations`" lazy="true" cascade="all">
<key column="`TeamID`" />
<many-to-many class="App.Data.Entities.Location,App.Data.Entities">
<column name="`LocationID`" />
</many-to-many>
</bag>
</class>
and Location.hbm.xml
<class name="App.Data.Entities.Location,App.Data.Entities" table="`Location`" lazy="true">
<id name="Locationid" column="`LocationID`" type="int">
<generator class="native" />
</id>
<property type="string" not-null="true" length="250" name="LocationName" column="`LocationName`" />
<property type="string" length="1000" name="Address" column="`Address`" />
<bag name="Teams" inverse="false" table="`TeamLocations`" lazy="true" cascade="all">
<key column="`LocationID`" />
<many-to-many class="App.Data.Entities.Team,App.Data.Entities">
<column name="`TeamID`" />
</many-to-many>
</bag>
</class>
Now I am trying to retrieve all teams which are based in a specific location using criteria API, which I am unable to..
Equivalent sql...
SELECT Team.TeamName, Location.LocationName
FROM Team INNER JOIN
TeamLocations ON Team.TeamID = TeamLocations.TeamID INNER JOIN
Location ON TeamLocations.LocationID = Location.LocationID
WHERE (TeamLocations.LocationID = 2)
and in asp.net code
ICriteria criteria = _session.CreateCriteria(typeof(Team)).SetFirstResult(startRowIndex).SetMaxResults(maximumRows);
if (deptID > 0)
{
Department dept = new Department(deptID);
criteria.Add(Expression.Eq(Team.PropertyNames.Department, dept)); //for department, which works fine.
}
if (locationIDs.Count > 0)
{
List<Location> locations = new List<Location>();
foreach (int locationID in locationIDs)
{
Location loc = new Location(locationID);
locations.Add(loc);
}
criteria.CreateCriteria("TeamLocations").Add(Expression.Eq(""TeamLocations"", locations));
}
return criteria.List<Team>();
This throws and error..
could not resolve property: TeamLocations of: App.Data.Entities.Location
which I cant seen to figure out :(
Correct me.. Thanks!
You can add a restriction to an association path using CreateCriteria or CreateAlias as I did below. I would have to know more about your model and mapping to understand why you can add a restriction on Team.PropertyNames.Department without aliasing it.
ICriteria criteria = _session.CreateCriteria(typeof(Team)).SetFirstResult(startRowIndex).SetMaxResults(maximumRows);
if (deptID > 0)
{
Department dept = new Department(deptID);
criteria.Add(Expression.Eq(Team.PropertyNames.Department, dept)); //for department, which works fine.
}
if (locationIDs.Count > 0)
{
// you may need to convert locationIds to an ICollection e.g.
// var ids = locationIds.ToArray();
criteria.CreateAlias("TeamLocations", "teamLocations");
criteria.Add(Restrictions.In("teamLocations.LocationId", locationIds));
}
return criteria.List<Team>();