我已经阅读了很多关于相同错误的问题,但是没有一个是为了匹配我的确切问题.我正在使用Fluent NHibernate访问对象的属性,本身是根对象的一部分.有些答案说我需要使用预测,其他的我需要使用加入,我认为它应该通过懒惰加载工作.
这是我的两个课程以及流畅的映射:
艺术家类
public class Artist { public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual IList<Album> Albums { get; set; } public virtual string MusicBrainzId { get; set; } public virtual string TheAudioDbId { get; set; } public Artist() { } } public class ArtistMap : ClassMap<Artist> { public ArtistMap() { LazyLoad(); Id(a => a.Id); Map(a => a.Name).Index("Name"); HasMany(a => a.Albums) .Cascade.All(); Map(a => a.MusicBrainzId); Map(a => a.TheAudioDbId); } }
专辑类
public class Album { public virtual int Id { get; set; } public virtual Artist Artist { get; set; } public virtual string Name { get; set; } public virtual IList<Track> Tracks { get; set; } public virtual DateTime ReleaseDate { get; set; } public virtual string TheAudioDbId { get; set; } public virtual string MusicBrainzId { get; set; } public Album() { } } public class AlbumMap : ClassMap<Album> { public AlbumMap() { LazyLoad(); Id(a => a.Id); References(a => a.Artist) .Cascade.All(); Map(a => a.Name).Index("Name"); HasMany(a => a.Tracks) .Cascade.All(); Map(a => a.ReleaseDate); Map(a => a.TheAudioDbId); Map(a => a.MusicBrainzId); } }
var riAlbum = session.QueryOver<Album>() .Where(x => x.Name == albumName && x.Artist.Name == artist) .List().FirstOrDefault();
当Fluent NHibernate尝试解析x.Artist.Name值时,会发生错误:
{“could not resolve property: Artist.Name of: Album”}
这样做的正确方法是什么?
解决方法
您必须将QueryOver查询视为(几乎)直接翻译成sql.考虑到这一点,想象这个SQL查询:
select Album.* from Album where Album.Name = 'SomeAlbumName' and Album.Artist.Name = 'SomeArtistName'
这将无法正常工作,因为您无法在sql语句中访问相关表的属性.您需要创建一个从Album到Artist的连接,然后使用Where子句:
var riAlbum = session.QueryOver<Album>() .Where(al => al.Name == albumName) .JoinQueryOver(al => al.Artist) .Where(ar => ar.Name == artistName) .List() .FirstOrDefault();
此外,由于您使用的是FirstOrDefault,您可能需要考虑将该逻辑移至数据库端.目前,您正在拉回符合您的标准的每个记录,然后取得第一个.您可以使用.Take将查询限制为1个结果:
var riAlbum = session.QueryOver<Album>() .Where(al => al.Name == albumName) .JoinQueryOver(al => al.Artist) .Where(ar => ar.Name == artistName) .Take(1) .SingleOrDefault<Album>();