问题
I have a data model of Country, State and City entities. Each City entity has a reference to a State, and each State has a reference to a Country (UML diagram here). This is much simplified from my actual data model.
For a list of cities in the UI I am retrieving Cities from the database using Nhibernate, and I want to (1) order by the name of the Country (the grandparent entity of City), and (2) eager load the whole structure. I can get NH to do either, but not both.
I get:
Query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=2,role=,tableName="Country",tableAlias=country4,origin="State" state1_,colums={state1_.Country_id ,className=NHGrandparentSortingSpike.Entities.Country}}] [.ThenFetch[NHGrandparentSortingSpike.Entities.City,NHGrandparentSortingSpike.Entities.State,NHGrandparentSortingSpike.Entities.Country](.Fetch[NHGrandparentSortingSpike.Entities.City,NHGrandparentSortingSpike.Entities.State](.OrderBy[NHGrandparentSortingSpike.Entities.City,System.String](NHibernate.Linq.NhQueryable`1[NHGrandparentSortingSpike.Entities.City], Quote((c, ) => (c.State.Country.Name)), ), Quote((c, ) => (c.State)), ), Quote((s, ) => (s.Country)), )]
Entities:
public class Country {
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual IList<State> States { get; set; }
...
}
public class State {
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual Country Country { get; set; }
public virtual IList<City> Cities { get; set; }
...
}
public class City {
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual State State { get; set; }
}
Mappings (using Fluent NHibernate):
public class CountryMap : ClassMap<Country> {
public CountryMap() {
Id(x => x.Id).Not.Nullable().GeneratedBy.Native();
Map(x => x.Name).Not.Nullable().Length(100);
HasMany(x => x.States).Inverse().Cascade.All();
}
}
public class StateMap : ClassMap<State> {
public StateMap() {
Id(x => x.Id).Not.Nullable().GeneratedBy.Native();
Map(x => x.Name).Not.Nullable().Length(100);
References(x => x.Country).Not.Nullable();
HasMany(x => x.Cities).Inverse().Cascade.All();
}
}
public class CityMap : ClassMap<City> {
public CityMap() {
Id(x => x.Id).Not.Nullable().GeneratedBy.Native();
Map(x => x.Name).Not.Nullable().Length(100);
References(x => x.State).Not.Nullable();
}
}
Queries: Lazy loading with ordering (this works as expected without errors, but issues too many SQL queries for my liking):
var cities = _cityRepo.All.OrderBy(c => c.State.Country.Name);
Eager loading but no ordering (this works as expected without errors, but isn't sorted so cannot be paged correctly):
var cities = _cityRepo.All.Fetch(c => c.State).ThenFetch(s => s.Country);
Eager loading with ordering (this doesn't work and throws the error above):
var cities = _cityRepo.All
.OrderBy(c => c.State.Country.Name)
.Fetch(c => c.State)
.ThenFetch(s => s.Country);
Here is a zip of a simple VS2008 console app using a SQLite in memory database demonstrating this issue: Download (2MB)
Any ideas?
Thanks.
来源:https://stackoverflow.com/questions/6481671/nhibernate-exception-when-ordering-entities-by-grandparent-property-when-eager-l